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