Whamcloud - gitweb
Minor cleanups and debugging statements added.
[fs/lustre-release.git] / lustre / llite / rw.c
1 /*
2  * Lustre Light I/O Page Cache
3  *
4  * Copyright (C) 2002, Cluster File Systems, Inc. 
5 */
6
7
8 #include <linux/config.h>
9 #include <linux/kernel.h>
10 #include <linux/mm.h>
11 #include <linux/string.h>
12 #include <linux/stat.h>
13 #include <linux/errno.h>
14 #include <linux/locks.h>
15 #include <linux/unistd.h>
16
17 #include <asm/system.h>
18 #include <asm/uaccess.h>
19
20 #include <linux/fs.h>
21 #include <linux/stat.h>
22 #include <asm/uaccess.h>
23 #include <linux/vmalloc.h>
24 #include <asm/segment.h>
25 #include <linux/mm.h>
26 #include <linux/pagemap.h>
27 #include <linux/smp_lock.h>
28
29 #include <linux/obd_support.h>
30 #include <linux/lustre_lib.h>
31 #include <linux/lustre_idl.h>
32 #include <linux/lustre_mds.h>
33 #include <linux/lustre_light.h>
34
35
36 static void inline ll_oa_from_inode(struct obdo *oa, struct inode *inode)
37 {
38         struct ll_inode_info *oinfo = ll_i2info(inode);
39
40         if ( oa->o_valid & OBD_MD_FLID )
41                 oa->o_id = oinfo->lli_objid;
42         if ( oa->o_valid & OBD_MD_FLATIME )
43                 oa->o_atime = inode->i_atime;
44         if ( oa->o_valid & OBD_MD_FLMTIME )
45                 oa->o_mtime = inode->i_mtime;
46         if ( oa->o_valid & OBD_MD_FLCTIME )
47                 oa->o_ctime = inode->i_ctime;
48         if ( oa->o_valid & OBD_MD_FLSIZE )
49                 oa->o_size = inode->i_size;
50         if ( oa->o_valid & OBD_MD_FLBLOCKS )   /* allocation of space */
51                 oa->o_blocks = inode->i_blocks;
52         if ( oa->o_valid & OBD_MD_FLBLKSZ )
53                 oa->o_blksize = inode->i_blksize;
54         if ( oa->o_valid & OBD_MD_FLMODE )
55                 oa->o_mode = inode->i_mode;
56         if ( oa->o_valid & OBD_MD_FLUID )
57                 oa->o_uid = inode->i_uid;
58         if ( oa->o_valid & OBD_MD_FLGID )
59                 oa->o_gid = inode->i_gid;
60         if ( oa->o_valid & OBD_MD_FLFLAGS )
61                 oa->o_flags = inode->i_flags;
62         if ( oa->o_valid & OBD_MD_FLNLINK )
63                 oa->o_nlink = inode->i_nlink;
64         if ( oa->o_valid & OBD_MD_FLGENER ) 
65                 oa->o_generation = inode->i_generation;
66
67         CDEBUG(D_INFO, "src inode %ld, dst obdo %ld valid 0x%08x\n",
68                inode->i_ino, (long)oa->o_id, oa->o_valid);
69         obdo_from_inode(oa, inode);
70         
71         /* this will transfer metadata for the logical object to 
72            the oa: that metadata could contain the constituent objects
73         */
74         if (ll_has_inline(inode)) {
75                 CDEBUG(D_INODE, "copying inline data from inode to obdo\n");
76                 memcpy(oa->o_inline, oinfo->lli_inline, OBD_INLINESZ);
77                 oa->o_obdflags |= OBD_FL_INLINEDATA;
78                 oa->o_valid |= OBD_MD_FLINLINE;
79         }
80 } /* ll_oa_from_inode */
81
82 /*
83  * Add a page to the dirty page list.
84  */
85 void set_page_dirty(struct page *page)
86 {
87         if (!test_and_set_bit(PG_dirty, &page->flags)) {
88                 struct address_space *mapping = page->mapping;
89
90                 if (mapping) {
91                         spin_lock(&pagecache_lock);
92                         list_del(&page->list);
93                         list_add(&page->list, &mapping->dirty_pages);
94                         spin_unlock(&pagecache_lock);
95
96                         if (mapping->host)
97                                 mark_inode_dirty_pages(mapping->host);
98                 }
99         }
100 }
101
102 /*
103  * Remove page from dirty list
104  */
105 void __set_page_clean(struct page *page)
106 {
107         struct address_space *mapping = page->mapping;
108         struct inode *inode;
109         
110         if (!mapping)
111                 return;
112
113         spin_lock(&pagecache_lock);
114         list_del(&page->list);
115         list_add(&page->list, &mapping->clean_pages);
116
117         inode = mapping->host;
118         if (list_empty(&mapping->dirty_pages)) { 
119                 CDEBUG(D_INODE, "inode clean\n");
120                 inode->i_state &= ~I_DIRTY_PAGES;
121         }
122         spin_unlock(&pagecache_lock);
123         EXIT;
124 }
125
126 inline void set_page_clean(struct page *page)
127 {
128         if (PageDirty(page)) { 
129                 ClearPageDirty(page);
130                 __set_page_clean(page);
131         }
132 }
133
134 /* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
135 static int ll_brw(int rw, struct inode *inode, struct page *page, int create)
136 {
137         obd_count        num_obdo = 1;
138         obd_count        bufs_per_obdo = 1;
139         struct obdo     *oa;
140         obd_size         count = PAGE_SIZE;
141         obd_off          offset = ((obd_off)page->index) << PAGE_SHIFT;
142         obd_flag         flags = create ? OBD_BRW_CREATE : 0;
143         int              err;
144
145         ENTRY;
146
147         oa = obdo_alloc();
148         if ( !oa ) {
149                 EXIT;
150                 return -ENOMEM;
151         }
152         oa->o_valid = OBD_MD_FLNOTOBD;
153         ll_oa_from_inode(oa, inode);
154
155         err = obd_brw(rw, IID(inode), num_obdo, &oa, &bufs_per_obdo,
156                                &page, &count, &offset, &flags);
157         //if ( !err )
158         //      ll_to_inode(inode, oa); /* copy o_blocks to i_blocks */
159
160         obdo_free(oa);
161         EXIT;
162         return err;
163 } /* ll_brw */
164
165 extern void set_page_clean(struct page *);
166
167 /* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
168 static int ll_commit_page(struct page *page, int create, int from, int to)
169 {
170         struct inode *inode = page->mapping->host;
171         obd_count        num_obdo = 1;
172         obd_count        bufs_per_obdo = 1;
173         struct obdo     *oa;
174         obd_size         count = to;
175         obd_off          offset = (((obd_off)page->index) << PAGE_SHIFT);
176         obd_flag         flags = create ? OBD_BRW_CREATE : 0;
177         int              err;
178
179         ENTRY;
180         oa = obdo_alloc();
181         if ( !oa ) {
182                 EXIT;
183                 return -ENOMEM;
184         }
185         oa->o_valid = OBD_MD_FLNOTOBD;
186         ll_oa_from_inode(oa, inode);
187
188         CDEBUG(D_INODE, "commit_page writing (at %d) to %d, count %Ld\n", 
189                from, to, count);
190
191         err = obd_brw(WRITE, IID(inode), num_obdo, &oa, &bufs_per_obdo,
192                                &page, &count, &offset, &flags);
193         if ( !err ) {
194                 SetPageUptodate(page);
195                 set_page_clean(page);
196         }
197
198         //if ( !err )
199         //      ll_to_inode(inode, oa); /* copy o_blocks to i_blocks */
200
201         obdo_free(oa);
202         EXIT;
203         return err;
204 } /* ll_brw */
205
206
207 /* returns the page unlocked, but with a reference */
208 int ll_readpage(struct file *file, struct page *page)
209 {
210         struct inode *inode = page->mapping->host;
211         int rc;
212
213         ENTRY;
214
215         if ( ((inode->i_size + PAGE_CACHE_SIZE -1)>>PAGE_SHIFT) 
216              <= page->index) {
217                 memset(kmap(page), 0, PAGE_CACHE_SIZE);
218                 kunmap(page);
219                 goto readpage_out;
220         }
221
222         if (Page_Uptodate(page)) {
223                 EXIT;
224                 goto readpage_out;
225         }
226
227         rc = ll_brw(READ, inode, page, 0);
228         if ( rc ) {
229                 EXIT; 
230                 return rc;
231         } 
232         /* PDEBUG(page, "READ"); */
233
234  readpage_out:
235         SetPageUptodate(page);
236         obd_unlock_page(page);
237         EXIT;
238         return 0;
239 } /* ll_readpage */
240
241
242
243 /* returns the page unlocked, but with a reference */
244 int ll_dir_readpage(struct file *file, struct page *page)
245 {
246         struct inode *inode = page->mapping->host;
247         struct ll_sb_info *sbi =
248                 (struct ll_sb_info *)(&inode->i_sb->u.generic_sbp);
249         char *buf;
250         __u64 offset;
251         int rc = 0;
252         struct ptlrep_hdr *hdr;
253
254         ENTRY;
255
256         if ( ((inode->i_size + PAGE_CACHE_SIZE -1)>>PAGE_SHIFT) 
257              <= page->index) {
258                 memset(kmap(page), 0, PAGE_CACHE_SIZE);
259                 kunmap(page);
260                 goto readpage_out;
261         }
262
263         if (Page_Uptodate(page)) {
264                 EXIT;
265                 goto readpage_out;
266         }
267
268         offset = page->index << PAGE_SHIFT; 
269         buf = kmap(page);
270         rc = mdc_readpage(sbi->ll_peer_ptr, inode->i_ino, S_IFDIR, offset, buf,
271                           NULL, &hdr);
272         kunmap(page); 
273         if ( rc ) {
274                 EXIT; 
275                 goto readpage_out;
276         } 
277
278         if ((rc = hdr->status)) {
279                 EXIT;
280                 goto readpage_out;
281         }
282
283         /* PDEBUG(page, "READ"); */
284
285         SetPageUptodate(page);
286  readpage_out:
287         unlock_page(page);
288         EXIT;
289         return rc;
290 } /* ll_dir_readpage */
291
292 int ll_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
293 {
294         struct inode *inode = page->mapping->host;
295         obd_off offset = ((obd_off)page->index) << PAGE_SHIFT;
296         int rc = 0;
297         ENTRY; 
298         
299         kmap(page);
300         if (Page_Uptodate(page)) { 
301                 EXIT;
302                 goto prepare_done;
303         }
304
305         if ( (from <= offset) && (to >= offset + PAGE_SIZE) ) {
306                 EXIT;
307                 return 0;
308         }
309         
310         rc = ll_brw(READ, inode, page, 0);
311         if ( !rc ) {
312                 SetPageUptodate(page);
313         } 
314
315  prepare_done:
316         set_page_dirty(page);
317         //SetPageDirty(page);
318         EXIT;
319         return rc;
320 }
321
322
323 /* select between SYNC and ASYNC I/O methods */
324 int ll_do_writepage(struct page *page, int sync)
325 {
326         struct inode *inode = page->mapping->host;
327         int err;
328
329         ENTRY;
330         /* PDEBUG(page, "WRITEPAGE"); */
331         /* XXX everything is synchronous now */
332         err = ll_brw(WRITE, inode, page, 1);
333
334         if ( !err ) {
335                 SetPageUptodate(page);
336                 set_page_clean(page);
337         }
338         /* PDEBUG(page,"WRITEPAGE"); */
339         EXIT;
340         return err;
341 } /* ll_do_writepage */
342
343
344
345 /* returns the page unlocked, but with a reference */
346 int ll_writepage(struct page *page)
347 {
348         int rc;
349         struct inode *inode = page->mapping->host;
350         ENTRY;
351         printk("---> writepage called ino %ld!\n", inode->i_ino);
352         BUG();
353         rc = ll_do_writepage(page, 1);
354         if ( !rc ) {
355                 set_page_clean(page);
356         } else {
357                 CDEBUG(D_INODE, "--> GRR %d\n", rc);
358         }
359         EXIT;
360         return rc;
361 }
362
363 void write_inode_pages(struct inode *inode)
364 {
365         struct list_head *tmp = &inode->i_mapping->dirty_pages;
366         
367         while ( (tmp = tmp->next) != &inode->i_mapping->dirty_pages) { 
368                 struct page *page;
369                 page = list_entry(tmp, struct page, list);
370                 ll_writepage(page);
371         }
372 }
373
374
375 int ll_commit_write(struct file *file, struct page *page, unsigned from, unsigned to)
376 {
377         struct inode *inode = page->mapping->host;
378         int rc = 0;
379         loff_t len = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
380         ENTRY;
381         CDEBUG(D_INODE, "commit write ino %ld (end at %Ld) from %d to %d ,ind %ld\n",
382                inode->i_ino, len, from, to, page->index);
383
384         rc = ll_commit_page(page, 1, from, to);
385
386         if (len > inode->i_size) {
387                 ll_set_size(inode, len);
388         }
389
390         kunmap(page);
391         EXIT;
392         return rc;
393 }
394
395
396 /*
397  * This does the "real" work of the write. The generic routine has
398  * allocated the page, locked it, done all the page alignment stuff
399  * calculations etc. Now we should just copy the data from user
400  * space and write it back to the real medium..
401  *
402  * If the writer ends up delaying the write, the writer needs to
403  * increment the page use counts until he is done with the page.
404  *
405  * Return value is the number of bytes written.
406  */
407 int ll_write_one_page(struct file *file, struct page *page,
408                          unsigned long offset, unsigned long bytes,
409                          const char * buf)
410 {
411         struct inode *inode = file->f_dentry->d_inode;
412         int err;
413
414         ENTRY;
415         /* We check for complete page writes here, as we then don't have to
416          * get the page before writing over everything anyways.
417          */
418         if ( !Page_Uptodate(page) && (offset != 0 || bytes != PAGE_SIZE) ) {
419                 err = ll_brw(READ, inode, page, 0);
420                 if ( err )
421                         return err;
422                 SetPageUptodate(page);
423         }
424
425         if (copy_from_user((u8*)page_address(page) + offset, buf, bytes))
426                 return -EFAULT;
427
428         lock_kernel();
429         err = ll_writepage(page);
430         unlock_kernel();
431
432         return (err < 0 ? err : bytes);
433 } /* ll_write_one_page */
434
435 /* 
436  * return an up to date page:
437  *  - if locked is true then is returned locked
438  *  - if create is true the corresponding disk blocks are created 
439  *  - page is held, i.e. caller must release the page
440  *
441  * modeled on NFS code.
442  */
443 struct page *ll_getpage(struct inode *inode, unsigned long offset,
444                            int create, int locked)
445 {
446         struct page * page;
447         int index;
448         int err;
449
450         ENTRY;
451
452         offset = offset & PAGE_CACHE_MASK;
453         CDEBUG(D_INFO, "ino: %ld, offset %ld, create %d, locked %d\n",
454                inode->i_ino, offset, create, locked);
455         index = offset >> PAGE_CACHE_SHIFT;
456
457         page = grab_cache_page(&inode->i_data, index);
458
459         /* Yuck, no page */
460         if (! page) {
461             printk(KERN_WARNING " grab_cache_page says no dice ...\n");
462             EXIT;
463             return NULL;
464         }
465
466         /* PDEBUG(page, "GETPAGE: got page - before reading\n"); */
467         /* now check if the data in the page is up to date */
468         if ( Page_Uptodate(page)) { 
469                 if (!locked) {
470                         if (PageLocked(page))
471                                 obd_unlock_page(page);
472                 } else {
473                         printk("file %s, line %d: expecting locked page\n",
474                                __FILE__, __LINE__); 
475                 }
476                 EXIT;
477                 return page;
478         } 
479
480         err = ll_brw(READ, inode, page, create);
481
482         if ( err ) {
483                 SetPageError(page);
484                 obd_unlock_page(page);
485                 EXIT;
486                 return page;
487         }
488
489         if ( !locked )
490                 obd_unlock_page(page);
491         SetPageUptodate(page);
492         /* PDEBUG(page,"GETPAGE - after reading"); */
493         EXIT;
494         return page;
495 } /* ll_getpage */
496
497
498 void ll_truncate(struct inode *inode)
499 {
500         struct obdo *oa;
501         int err;
502         ENTRY;
503
504         //ll_dequeue_pages(inode);
505
506         oa = obdo_alloc();
507         if ( !oa ) {
508                 /* XXX This would give an inconsistent FS, so deal with it as
509                  * best we can for now - an obdo on the stack is not pretty.
510                  */
511                 struct obdo obdo;
512
513                 printk(__FUNCTION__ ": obdo_alloc failed - using stack!\n");
514
515                 obdo.o_valid = OBD_MD_FLNOTOBD;
516                 ll_oa_from_inode(&obdo, inode);
517
518                 err = obd_punch(IID(inode), &obdo, 0, obdo.o_size);
519         } else {
520                 oa->o_valid = OBD_MD_FLNOTOBD;
521                 ll_oa_from_inode(oa, inode);
522
523                 CDEBUG(D_INFO, "calling punch for %ld (%Lu bytes at 0)\n",
524                        (long)oa->o_id, oa->o_size);
525                 err = obd_punch(IID(inode), oa, oa->o_size, 0);
526
527                 obdo_free(oa);
528         }
529
530         if (err) {
531                 printk(__FUNCTION__ ": obd_truncate fails (%d)\n", err);
532                 EXIT;
533                 return;
534         }
535         EXIT;
536 } /* ll_truncate */
537
538 struct address_space_operations ll_aops = {
539         readpage: ll_readpage,
540         writepage: ll_writepage,
541         sync_page: block_sync_page,
542         prepare_write: ll_prepare_write, 
543         commit_write: ll_commit_write,
544         bmap: NULL
545 };
546
547
548 struct address_space_operations ll_dir_aops = {
549         readpage: ll_dir_readpage
550 };