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