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