Whamcloud - gitweb
cleanups coming from the new functions/macros
[fs/lustre-release.git] / lustre / obdfs / rw.c
1 /*
2  * OBDFS Super operations
3  *
4  * This code is issued under the GNU General Public License.
5  * See the file COPYING in this distribution
6  *
7  * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
8  * Copryright (C) 1999 Stelias Computing Inc, 
9  *                (author Peter J. Braam <braam@stelias.com>)
10  * Copryright (C) 1999 Seagate Technology Inc.
11 */
12
13
14 #include <linux/config.h>
15 #include <linux/kernel.h>
16 #include <linux/mm.h>
17 #include <linux/string.h>
18 #include <linux/stat.h>
19 #include <linux/errno.h>
20 #include <linux/locks.h>
21 #include <linux/unistd.h>
22
23 #include <asm/system.h>
24 #include <asm/uaccess.h>
25
26 #include <linux/fs.h>
27 #include <linux/stat.h>
28 #include <asm/uaccess.h>
29 #include <linux/vmalloc.h>
30 #include <asm/segment.h>
31 #include <linux/mm.h>
32 #include <linux/pagemap.h>
33 #include <linux/smp_lock.h>
34
35 #include <linux/obd_support.h>
36 #include <linux/obd_ext2.h>
37 #include <linux/obdfs.h>
38
39 void obdfs_change_inode(struct inode *inode);
40
41 static int cache_writes = 0;
42
43
44 /* page cache support stuff */ 
45
46
47 /*
48  * Add a page to the dirty page list.
49  */
50 void set_page_dirty(struct page *page)
51 {
52         if (!test_and_set_bit(PG_dirty, &page->flags)) {
53                 struct address_space *mapping = page->mapping;
54
55                 if (mapping) {
56                         spin_lock(&pagecache_lock);
57                         list_del(&page->list);
58                         list_add(&page->list, &mapping->dirty_pages);
59                         spin_unlock(&pagecache_lock);
60
61                         if (mapping->host)
62                                 mark_inode_dirty_pages(mapping->host);
63                 }
64         }
65 }
66
67 /*
68  * Remove page from dirty list
69  */
70 void __set_page_clean(struct page *page)
71 {
72         struct address_space *mapping = page->mapping;
73         struct inode *inode;
74         
75         if (!mapping)
76                 return;
77
78         spin_lock(&pagecache_lock);
79         list_del(&page->list);
80         list_add(&page->list, &mapping->clean_pages);
81
82         inode = mapping->host;
83         if (list_empty(&mapping->dirty_pages)) { 
84                 CDEBUG(D_INODE, "inode clean\n");
85                 inode->i_state &= ~I_DIRTY_PAGES;
86         }
87         spin_unlock(&pagecache_lock);
88         EXIT;
89 }
90
91 inline void set_page_clean(struct page *page)
92 {
93         if (PageDirty(page)) { 
94                 ClearPageDirty(page);
95                 __set_page_clean(page);
96         }
97 }
98
99 /* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
100 static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create)
101 {
102         obd_count        num_obdo = 1;
103         obd_count        bufs_per_obdo = 1;
104         struct obdo     *oa;
105         obd_size         count = PAGE_SIZE;
106         obd_off          offset = ((obd_off)page->index) << PAGE_SHIFT;
107         obd_flag         flags = create ? OBD_BRW_CREATE : 0;
108         int              err;
109
110         ENTRY;
111
112         oa = obdo_alloc();
113         if ( !oa ) {
114                 EXIT;
115                 return -ENOMEM;
116         }
117         oa->o_valid = OBD_MD_FLNOTOBD;
118         obdfs_from_inode(oa, inode);
119
120         err = obd_brw(rw, IID(inode), num_obdo, &oa, &bufs_per_obdo,
121                        &page, &count, &offset, &flags);
122         //if ( !err )
123         //      obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
124
125         obdo_free(oa);
126         EXIT;
127         return err;
128 } /* obdfs_brw */
129
130 extern void set_page_clean(struct page *);
131
132 /* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
133 static int obdfs_commit_page(struct page *page, int create, int from, int to)
134 {
135         struct inode *inode = page->mapping->host;
136         obd_count        num_obdo = 1;
137         obd_count        bufs_per_obdo = 1;
138         struct obdo     *oa;
139         obd_size         count = to;
140         obd_off          offset = (((obd_off)page->index) << PAGE_SHIFT);
141         obd_flag         flags = create ? OBD_BRW_CREATE : 0;
142         int              err;
143
144         ENTRY;
145         oa = obdo_alloc();
146         if ( !oa ) {
147                 EXIT;
148                 return -ENOMEM;
149         }
150         oa->o_valid = OBD_MD_FLNOTOBD;
151         obdfs_from_inode(oa, inode);
152
153         CDEBUG(D_INODE, "commit_page writing (at %d) to %d, count %Ld\n", 
154                from, to, count);
155
156         err = obd_brw(WRITE, IID(inode), num_obdo, &oa, &bufs_per_obdo,
157                                &page, &count, &offset, &flags);
158         if ( !err ) {
159                 SetPageUptodate(page);
160                 set_page_clean(page);
161         }
162
163         //if ( !err )
164         //      obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
165
166         obdo_free(oa);
167         EXIT;
168         return err;
169 } /* obdfs_brw */
170
171 /* returns the page unlocked, but with a reference */
172 int obdfs_writepage(struct page *page)
173 {
174         int rc;
175         struct inode *inode = page->mapping->host;
176         ENTRY;
177         printk("---> writepage called ino %ld!\n", inode->i_ino);
178         BUG();
179         rc = obdfs_brw(WRITE, inode, page, 1);
180         if ( !rc ) {
181                 set_page_clean(page);
182         } else {
183                 CDEBUG(D_INODE, "--> GRR %d\n", rc);
184         }
185         EXIT;
186         return rc;
187 }
188
189
190 void write_inode_pages(struct inode *inode)
191 {
192         struct list_head *tmp = &inode->i_mapping->dirty_pages;
193         
194         while ( (tmp = tmp->next) != &inode->i_mapping->dirty_pages) { 
195                 struct page *page;
196                 page = list_entry(tmp, struct page, list);
197                 obdfs_writepage(page);
198         }
199 }
200
201
202 /* returns the page unlocked, but with a reference */
203 int obdfs_readpage(struct file *file, struct page *page)
204 {
205         struct inode *inode = page->mapping->host;
206         int rc;
207
208         ENTRY;
209
210         if ( ((inode->i_size + PAGE_CACHE_SIZE -1)>>PAGE_SHIFT) 
211              <= page->index) {
212                 memset(kmap(page), 0, PAGE_CACHE_SIZE);
213                 kunmap(page);
214                 goto readpage_out;
215         }
216
217         if (Page_Uptodate(page)) {
218                 EXIT;
219                 goto readpage_out;
220         }
221
222         rc = obdfs_brw(READ, inode, page, 0);
223         if ( rc ) {
224                 EXIT; 
225                 return rc;
226         } 
227         /* PDEBUG(page, "READ"); */
228
229  readpage_out:
230         SetPageUptodate(page);
231         obd_unlock_page(page);
232         EXIT;
233         return 0;
234 } /* obdfs_readpage */
235
236 int obdfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
237 {
238         struct inode *inode = page->mapping->host;
239         obd_off offset = ((obd_off)page->index) << PAGE_SHIFT;
240         int rc = 0;
241         ENTRY; 
242         
243         kmap(page);
244         if (Page_Uptodate(page)) { 
245                 EXIT;
246                 goto prepare_done;
247         }
248
249         if ( (from <= offset) && (to >= offset + PAGE_SIZE) ) {
250                 EXIT;
251                 return 0;
252         }
253         
254         rc = obdfs_brw(READ, inode, page, 0);
255         if ( !rc ) {
256                 SetPageUptodate(page);
257         } 
258
259  prepare_done:
260         set_page_dirty(page);
261         //SetPageDirty(page);
262         EXIT;
263         return rc;
264 }
265
266
267 #if 0
268
269
270
271 static kmem_cache_t *obdfs_pgrq_cachep = NULL;
272
273 int obdfs_init_pgrqcache(void)
274 {
275         ENTRY;
276         if (obdfs_pgrq_cachep == NULL) {
277                 CDEBUG(D_CACHE, "allocating obdfs_pgrq_cache\n");
278                 obdfs_pgrq_cachep = kmem_cache_create("obdfs_pgrq",
279                                                       sizeof(struct obdfs_pgrq),
280                                                       0, SLAB_HWCACHE_ALIGN,
281                                                       NULL, NULL);
282                 if (obdfs_pgrq_cachep == NULL) {
283                         EXIT;
284                         return -ENOMEM;
285                 } else {
286                         CDEBUG(D_CACHE, "allocated cache at %p\n",
287                                obdfs_pgrq_cachep);
288                 }
289         } else {
290                 CDEBUG(D_CACHE, "using existing cache at %p\n",
291                        obdfs_pgrq_cachep);
292         }
293         EXIT;
294         return 0;
295 } /* obdfs_init_wreqcache */
296
297 inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq)
298 {
299         --obdfs_cache_count;
300         CDEBUG(D_INFO, "deleting page %p from list [count %ld]\n",
301                pgrq->rq_page, obdfs_cache_count);
302         list_del(&pgrq->rq_plist);
303         OBDClearCachePage(pgrq->rq_page);
304         kmem_cache_free(obdfs_pgrq_cachep, pgrq);
305 }
306
307 void obdfs_cleanup_pgrqcache(void)
308 {
309         ENTRY;
310         if (obdfs_pgrq_cachep != NULL) {
311                 CDEBUG(D_CACHE, "destroying obdfs_pgrqcache at %p, count %ld\n",
312                        obdfs_pgrq_cachep, obdfs_cache_count);
313                 if (kmem_cache_destroy(obdfs_pgrq_cachep))
314                         printk(KERN_INFO __FUNCTION__
315                                ": unable to free all of cache\n");
316                 obdfs_pgrq_cachep = NULL;
317         } else
318                 printk(KERN_INFO __FUNCTION__ ": called with NULL pointer\n");
319
320         EXIT;
321 } /* obdfs_cleanup_wreqcache */
322
323
324 /* called with the list lock held */
325 static struct page *obdfs_find_page_index(struct inode *inode,
326                                           unsigned long index)
327 {
328         struct list_head *page_list = obdfs_iplist(inode);
329         struct list_head *tmp;
330         struct page *page;
331
332         ENTRY;
333
334         CDEBUG(D_INFO, "looking for inode %ld pageindex %ld\n",
335                inode->i_ino, index);
336         OIDEBUG(inode);
337
338         if (list_empty(page_list)) {
339                 EXIT;
340                 return NULL;
341         }
342         tmp = page_list;
343         while ( (tmp = tmp->next) != page_list ) {
344                 struct obdfs_pgrq *pgrq;
345
346                 pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist);
347                 page = pgrq->rq_page;
348                 if (index == page->index) {
349                         CDEBUG(D_INFO,
350                                "INDEX SEARCH found page %p, index %ld\n",
351                                page, index);
352                         EXIT;
353                         return page;
354                 }
355         } 
356
357         EXIT;
358         return NULL;
359 } /* obdfs_find_page_index */
360
361
362 /* call and free pages from Linux page cache: called with io lock on inodes */
363 int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io,
364                     obd_count num_obdos, struct obdo **obdos,
365                     obd_count *oa_bufs, struct page **pages, char **bufs,
366                     obd_size *counts, obd_off *offsets, obd_flag *flags)
367 {
368         int err;
369
370         ENTRY;
371         CDEBUG(D_INFO, "writing %d page(s), %d obdo(s) in vector\n",
372                num_io, num_obdos);
373         if (obd_debug_level & D_INFO) { /* DEBUGGING */
374                 int i;
375                 printk("OBDOS: ");
376                 for (i = 0; i < num_obdos; i++)
377                         printk("%ld:0x%p ", (long)obdos[i]->o_id, obdos[i]);
378
379                 printk("\nPAGES: ");
380                 for (i = 0; i < num_io; i++)
381                         printk("0x%p ", pages[i]);
382                 printk("\n");
383         }
384
385         err = obd_brw(WRITE, IID(inodes[0]), num_obdos, obdos,
386                                   oa_bufs, pages, counts, offsets, flags);
387
388         CDEBUG(D_INFO, "BRW done\n");
389         /* release the pages from the page cache */
390         while ( num_io > 0 ) {
391                 --num_io;
392                 CDEBUG(D_INFO, "calling put_page for %p, index %ld\n",
393                        pages[num_io], pages[num_io]->index);
394                 /* PDEBUG(pages[num_io], "do_vec_wr"); */
395                 put_page(pages[num_io]);
396                 /* PDEBUG(pages[num_io], "do_vec_wr"); */
397         }
398         CDEBUG(D_INFO, "put_page done\n");
399
400         while ( num_obdos > 0) {
401                 --num_obdos;
402                 CDEBUG(D_INFO, "free obdo %ld\n",(long)obdos[num_obdos]->o_id);
403                 /* copy o_blocks to i_blocks */
404                 obdfs_set_size (inodes[num_obdos], obdos[num_obdos]->o_size);
405                 //obdfs_to_inode(inodes[num_obdos], obdos[num_obdos]);
406                 obdo_free(obdos[num_obdos]);
407         }
408         CDEBUG(D_INFO, "obdo_free done\n");
409         EXIT;
410         return err;
411 }
412
413
414 /*
415  * Add a page to the write request cache list for later writing.
416  * ASYNCHRONOUS write method.
417  */
418 static int obdfs_add_page_to_cache(struct inode *inode, struct page *page)
419 {
420         int err = 0;
421         ENTRY;
422
423         /* The PG_obdcache bit is cleared by obdfs_pgrq_del() BEFORE the page
424          * is written, so at worst we will write the page out twice.
425          *
426          * If the page has the PG_obdcache bit set, then the inode MUST be
427          * on the superblock dirty list so we don't need to check this.
428          * Dirty inodes are removed from the superblock list ONLY when they
429          * don't have any more cached pages.  It is possible to have an inode
430          * with no dirty pages on the superblock list, but not possible to
431          * have an inode with dirty pages NOT on the superblock dirty list.
432          */
433         if (!OBDAddCachePage(page)) {
434                 struct obdfs_pgrq *pgrq;
435                 pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL);
436                 if (!pgrq) {
437                         OBDClearCachePage(page);
438                         EXIT;
439                         return -ENOMEM;
440                 }
441                 /* not really necessary since we set all pgrq fields here
442                 memset(pgrq, 0, sizeof(*pgrq)); 
443                 */
444                 
445                 pgrq->rq_page = page;
446                 pgrq->rq_jiffies = jiffies;
447                 get_page(pgrq->rq_page);
448
449                 obd_down(&obdfs_i2sbi(inode)->osi_list_mutex);
450                 list_add(&pgrq->rq_plist, obdfs_iplist(inode));
451                 obdfs_cache_count++;
452                 //printk("-- count %d\n", obdfs_cache_count);
453
454                 /* If inode isn't already on superblock inodes list, add it.
455                  *
456                  * We increment the reference count on the inode to keep it
457                  * from being freed from memory.  This _should_ be an iget()
458                  * with an iput() in both flush_reqs() and put_inode(), but
459                  * since put_inode() is called from iput() we can't call iput()
460                  * again there.  Instead we just increment/decrement i_count,
461                  * which is mostly what iget/iput do for an inode in memory.
462                  */
463                 if ( list_empty(obdfs_islist(inode)) ) {
464                         atomic_inc(&inode->i_count);
465                         CDEBUG(D_INFO,
466                                "adding inode %ld to superblock list %p\n",
467                                inode->i_ino, obdfs_slist(inode));
468                         list_add(obdfs_islist(inode), obdfs_slist(inode));
469                 }
470                 obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
471
472         }
473
474         /* XXX For testing purposes, we can write out the page here.
475         err = obdfs_flush_reqs(obdfs_slist(inode), ~0UL);
476          */
477
478         EXIT;
479         return err;
480 } /* obdfs_add_page_to_cache */
481
482 void rebalance(void)
483 {
484         if (obdfs_cache_count > 60000) {
485                 printk("-- count %ld\n", obdfs_cache_count);
486                 //obdfs_flush_dirty_pages(~0UL);
487                 printk("-- count %ld\n", obdfs_cache_count);
488         }
489 }
490
491
492
493 /* select between SYNC and ASYNC I/O methods */
494 int obdfs_do_writepage(struct page *page, int sync)
495 {
496         struct inode *inode = page->mapping->host;
497         int err;
498
499         ENTRY;
500         /* PDEBUG(page, "WRITEPAGE"); */
501         if ( sync )
502                 err = obdfs_brw(WRITE, inode, page, 1);
503         else {
504                 err = obdfs_add_page_to_cache(inode, page);
505                 CDEBUG(D_INFO, "DO_WR ino: %ld, page %p, err %d, uptodate %d\n",
506                        inode->i_ino, page, err, Page_Uptodate(page));
507         }
508                 
509         if ( !err ) {
510                 SetPageUptodate(page);
511                 set_page_clean(page);
512         }
513         /* PDEBUG(page,"WRITEPAGE"); */
514         EXIT;
515         return err;
516 } /* obdfs_do_writepage */
517
518
519
520
521 #endif
522
523 int obdfs_commit_write(struct file *file, struct page *page, unsigned from, unsigned to)
524 {
525         struct inode *inode = page->mapping->host;
526         int rc = 0;
527         loff_t len = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
528         ENTRY;
529         CDEBUG(D_INODE, "commit write ino %ld (end at %Ld) from %d to %d ,ind %ld\n",
530                inode->i_ino, len, from, to, page->index);
531
532
533         if (cache_writes == 0) { 
534                 rc = obdfs_commit_page(page, 1, from, to);
535         }
536
537         if (len > inode->i_size) {
538                 obdfs_set_size(inode, len);
539         }
540
541         kunmap(page);
542         EXIT;
543         return rc;
544 }
545
546
547 /*
548  * This does the "real" work of the write. The generic routine has
549  * allocated the page, locked it, done all the page alignment stuff
550  * calculations etc. Now we should just copy the data from user
551  * space and write it back to the real medium..
552  *
553  * If the writer ends up delaying the write, the writer needs to
554  * increment the page use counts until he is done with the page.
555  *
556  * Return value is the number of bytes written.
557  */
558 int obdfs_write_one_page(struct file *file, struct page *page,
559                          unsigned long offset, unsigned long bytes,
560                          const char * buf)
561 {
562         struct inode *inode = file->f_dentry->d_inode;
563         int err;
564
565         ENTRY;
566         /* We check for complete page writes here, as we then don't have to
567          * get the page before writing over everything anyways.
568          */
569         if ( !Page_Uptodate(page) && (offset != 0 || bytes != PAGE_SIZE) ) {
570                 err = obdfs_brw(READ, inode, page, 0);
571                 if ( err )
572                         return err;
573                 SetPageUptodate(page);
574         }
575
576         if (copy_from_user((u8*)page_address(page) + offset, buf, bytes))
577                 return -EFAULT;
578
579         lock_kernel();
580         err = obdfs_writepage(page);
581         unlock_kernel();
582
583         return (err < 0 ? err : bytes);
584 } /* obdfs_write_one_page */
585
586 /* 
587  * return an up to date page:
588  *  - if locked is true then is returned locked
589  *  - if create is true the corresponding disk blocks are created 
590  *  - page is held, i.e. caller must release the page
591  *
592  * modeled on NFS code.
593  */
594 struct page *obdfs_getpage(struct inode *inode, unsigned long offset,
595                            int create, int locked)
596 {
597         struct page * page;
598         int index;
599         int err;
600
601         ENTRY;
602
603         offset = offset & PAGE_CACHE_MASK;
604         CDEBUG(D_INFO, "ino: %ld, offset %ld, create %d, locked %d\n",
605                inode->i_ino, offset, create, locked);
606         index = offset >> PAGE_CACHE_SHIFT;
607
608         page = grab_cache_page(&inode->i_data, index);
609
610         /* Yuck, no page */
611         if (! page) {
612             printk(KERN_WARNING " grab_cache_page says no dice ...\n");
613             EXIT;
614             return NULL;
615         }
616
617         /* PDEBUG(page, "GETPAGE: got page - before reading\n"); */
618         /* now check if the data in the page is up to date */
619         if ( Page_Uptodate(page)) { 
620                 if (!locked) {
621                         if (PageLocked(page))
622                                 obd_unlock_page(page);
623                 } else {
624                         printk("file %s, line %d: expecting locked page\n",
625                                __FILE__, __LINE__); 
626                 }
627                 EXIT;
628                 return page;
629         } 
630
631         err = obdfs_brw(READ, inode, page, create);
632
633         if ( err ) {
634                 SetPageError(page);
635                 obd_unlock_page(page);
636                 EXIT;
637                 return page;
638         }
639
640         if ( !locked )
641                 obd_unlock_page(page);
642         SetPageUptodate(page);
643         /* PDEBUG(page,"GETPAGE - after reading"); */
644         EXIT;
645         return page;
646 } /* obdfs_getpage */
647
648
649 void obdfs_truncate(struct inode *inode)
650 {
651         struct obdo *oa;
652         int err;
653         ENTRY;
654
655         //obdfs_dequeue_pages(inode);
656         oa = obdo_alloc();
657         if ( !oa ) {
658                 err = -ENOMEM;
659                 printk(__FUNCTION__ ": obdo_alloc failed!\n");
660         } else {
661                 oa->o_valid = OBD_MD_FLNOTOBD;
662                 obdfs_from_inode(oa, inode);
663
664                 CDEBUG(D_INFO, "calling punch for %ld (%Lu bytes at 0)\n",
665                        (long)oa->o_id, oa->o_size);
666                 err = obd_punch(IID(inode), oa, oa->o_size, 0);
667
668                 obdo_free(oa);
669         }
670
671         if (err) {
672                 printk(__FUNCTION__ ": obd_truncate fails (%d)\n", err);
673                 EXIT;
674                 return;
675         }
676         EXIT;
677 } /* obdfs_truncate */
678
679 struct address_space_operations obdfs_aops = {
680         readpage: obdfs_readpage,
681         writepage: obdfs_writepage,
682         sync_page: block_sync_page,
683         prepare_write: obdfs_prepare_write, 
684         commit_write: obdfs_commit_write,
685         bmap: NULL
686 };