Whamcloud - gitweb
Cleanup : no more "sim" now "ext2"
[fs/lustre-release.git] / lustre / obdfs / rw.c
1 /*
2  * OBDFS Super operations
3  *
4  * Copryright (C) 1999 Stelias Computing Inc, 
5  *                (author Peter J. Braam <braam@stelias.com>)
6  * Copryright (C) 1999 Seagate Technology Inc.
7  */
8
9
10 #include <linux/config.h>
11 #include <linux/kernel.h>
12 #include <linux/mm.h>
13 #include <linux/string.h>
14 #include <linux/stat.h>
15 #include <linux/errno.h>
16 #include <linux/locks.h>
17 #include <linux/unistd.h>
18
19 #include <asm/system.h>
20 #include <asm/uaccess.h>
21
22 #include <linux/fs.h>
23 #include <linux/stat.h>
24 #include <asm/uaccess.h>
25 #include <linux/vmalloc.h>
26 #include <asm/segment.h>
27 #include <linux/mm.h>
28 #include <linux/pagemap.h>
29 #include <linux/smp_lock.h>
30
31 #include <linux/obd_support.h>
32 #include <linux/obd_sim.h>
33 #include <linux/obdfs.h>
34
35 int console_loglevel;
36
37 /* VFS super_block ops */
38
39 /* returns the page unlocked, but with a reference */
40 int obdfs_readpage(struct file *file, struct page *page)
41 {
42         struct inode *inode = file->f_dentry->d_inode;
43         int rc;
44
45         ENTRY;
46
47         /* XXX flush stuff */
48         PDEBUG(page, "READ");
49         rc =  iops(inode)->o_brw(READ, iid(inode),inode, page, 0);
50         if (rc == PAGE_SIZE ) {
51                 SetPageUptodate(page);
52                 UnlockPage(page);
53         } 
54         PDEBUG(page, "READ");
55         if ( rc == PAGE_SIZE ) 
56                 rc = 0;
57         return rc;
58
59 }
60
61 /*
62  * This does the "real" work of the write. The generic routine has
63  * allocated the page, locked it, done all the page alignment stuff
64  * calculations etc. Now we should just copy the data from user
65  * space and write it back to the real medium..
66  *
67  * If the writer ends up delaying the write, the writer needs to
68  * increment the page use counts until he is done with the page.
69  */
70 int obdfs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
71 {
72         long status;
73         struct inode *inode = file->f_dentry->d_inode;
74
75         ENTRY;
76         if ( !Page_Uptodate(page) ) {
77                 status =  iops(inode)->o_brw(READ, iid(inode), inode, page, 1);
78                 if (status == PAGE_SIZE ) {
79                         SetPageUptodate(page);
80                 } else { 
81                         return status;
82                 }
83         }
84         bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
85         status = -EFAULT;
86
87         if (bytes) {
88
89                 lock_kernel();
90                 status = obdfs_writepage(file, page);
91                 unlock_kernel();
92         }
93         EXIT;
94         if ( status != PAGE_SIZE ) 
95                 return status;
96         else
97                 return bytes;
98 }
99
100
101
102
103 /* returns the page unlocked, but with a reference */
104 int obdfs_writepage(struct file *file, struct page *page)
105 {
106         struct inode *inode = file->f_dentry->d_inode;
107         int rc;
108
109         ENTRY;
110         PDEBUG(page, "WRITEPAGE");
111         /* XXX flush stuff */
112
113         rc = iops(inode)->o_brw(WRITE, iid(inode), inode, page, 1);
114
115         SetPageUptodate(page);
116         PDEBUG(page,"WRITEPAGE");
117         return rc;
118 }
119
120
121 void report_inode(struct page * page) {
122         struct inode *inode = (struct inode *)0;
123         int offset = (int)&inode->i_data;
124         inode = (struct inode *)( (char *)page->mapping - offset);
125         if ( inode->i_sb->s_magic == 0x4711 )
126                 printk("----> ino %ld , dev %d\n", inode->i_ino, inode->i_dev);
127 }
128
129 /* 
130    return an up to date page:
131     - if locked is true then is returned locked
132     - if create is true the corresponding disk blocks are created 
133     - page is held, i.e. caller must release the page
134
135    modeled on NFS code.
136 */
137 struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked)
138 {
139         struct page *page_cache;
140         struct page ** hash;
141         struct page * page;
142         int rc;
143
144         ENTRY;
145
146         offset = offset & PAGE_CACHE_MASK;
147         CDEBUG(D_INODE, "\n");
148         
149         page = NULL;
150         page_cache = page_cache_alloc();
151         if ( ! page_cache ) 
152                 return NULL;
153         CDEBUG(D_INODE, "page_cache %p\n", page_cache);
154
155         hash = page_hash(&inode->i_data, offset);
156  repeat:
157         CDEBUG(D_INODE, "Finding page\n");
158         IDEBUG(inode);
159
160         page = __find_lock_page(&inode->i_data, offset, hash); 
161         if ( page ) {
162                 CDEBUG(D_INODE, "Page found freeing\n");
163                 page_cache_free(page_cache);
164         } else {
165                 page = page_cache;
166                 if ( page->buffers ) {
167                         PDEBUG(page, "GETPAGE: buffers bug\n");
168                         UnlockPage(page);
169                         return NULL;
170                 }
171                 if (add_to_page_cache_unique(page, &inode->i_data, offset, hash)) {
172                         page_cache_release(page);
173                         CDEBUG(D_INODE, "Someone raced: try again\n");
174                         goto repeat;
175                 }
176         }
177
178         PDEBUG(page, "GETPAGE: got page - before reading\n");
179         /* now check if the data in the page is up to date */
180         if ( Page_Uptodate(page)) { 
181                 if (!locked)
182                         UnlockPage(page);
183                 EXIT;
184                 return page;
185         } 
186
187         /* it's not: read it */
188         if (! page) {
189             printk("get_page_map says no dice ...\n");
190             return 0;
191             }
192
193
194
195         rc = iops(inode)->o_brw(READ, iid(inode), inode, page, create);
196         if ( rc != PAGE_SIZE ) {
197                 SetPageError(page);
198                 UnlockPage(page);
199                 return page;
200         }
201
202         if ( !locked )
203                 UnlockPage(page);
204         SetPageUptodate(page);
205         PDEBUG(page,"GETPAGE - after reading");
206         EXIT;
207         return page;
208 }
209
210
211 struct file_operations obdfs_file_ops = {
212         NULL,                   /* lseek - default */
213         generic_file_read,      /* read */
214         obdfs_file_write,       /* write - bad */
215         obdfs_readdir,          /* readdir */
216         NULL,                   /* poll - default */
217         NULL,                   /* ioctl */
218         NULL,                   /* mmap */
219         NULL,                   /* no special open code */
220         NULL,                   /* flush */
221         NULL,                   /* no special release code */
222         NULL,                   /* fsync */
223         NULL,                   /* fasync */
224         NULL,                   /* check_media_change */
225         NULL                    /* revalidate */
226 };
227
228 struct inode_operations obdfs_inode_ops = {
229         &obdfs_file_ops,        /* default directory file-ops */
230         obdfs_create,   /* create */
231         obdfs_lookup,   /* lookup */
232         obdfs_link,     /* link */
233         obdfs_unlink,   /* unlink */
234         obdfs_symlink,  /* symlink */
235         obdfs_mkdir,    /* mkdir */
236         obdfs_rmdir,    /* rmdir */
237         obdfs_mknod,    /* mknod */
238         obdfs_rename,   /* rename */
239         NULL,           /* readlink */
240         NULL,           /* follow_link */
241         NULL,           /* get_block */
242         obdfs_readpage, /* readpage */
243         obdfs_writepage, /* writepage */
244         NULL,           /* flushpage */
245         NULL,           /* truncate */
246         NULL,           /* permission */
247         NULL,           /* smap */
248         NULL            /* revalidate */
249 };