Merge with Linu 2.4.0-test6-pre6.
[linux-2.6/linux-mips.git] / fs / smbfs / file.c
blob135e8707cc68a679b8dfdf6edda7717a855ad3db
1 /*
2 * file.c
4 * Copyright (C) 1995, 1996, 1997 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
7 * Please add a note about your changes to smbfs in the ChangeLog file.
8 */
10 #include <linux/sched.h>
11 #include <linux/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/fcntl.h>
14 #include <linux/stat.h>
15 #include <linux/mm.h>
16 #include <linux/malloc.h>
17 #include <linux/pagemap.h>
18 #include <linux/smp_lock.h>
20 #include <asm/uaccess.h>
21 #include <asm/system.h>
23 #include <linux/smbno.h>
24 #include <linux/smb_fs.h>
26 #include "smb_debug.h"
28 static int
29 smb_fsync(struct file *file, struct dentry * dentry, int datasync)
31 VERBOSE("sync file %s/%s\n", DENTRY_PATH(dentry));
32 return 0;
36 * Read a page synchronously.
38 static int
39 smb_readpage_sync(struct dentry *dentry, struct page *page)
41 char *buffer = page_address(page);
42 unsigned long offset = page->index << PAGE_CACHE_SHIFT;
43 int rsize = smb_get_rsize(server_from_dentry(dentry));
44 int count = PAGE_SIZE;
45 int result;
47 VERBOSE("file %s/%s, count=%d@%ld, rsize=%d\n",
48 DENTRY_PATH(dentry), count, offset, rsize);
50 result = smb_open(dentry, SMB_O_RDONLY);
51 if (result < 0)
53 PARANOIA("%s/%s open failed, error=%d\n",
54 DENTRY_PATH(dentry), result);
55 goto io_error;
58 do {
59 if (count < rsize)
60 rsize = count;
62 result = smb_proc_read(dentry, offset, rsize, buffer);
63 if (result < 0)
64 goto io_error;
66 count -= result;
67 offset += result;
68 buffer += result;
69 dentry->d_inode->i_atime = CURRENT_TIME;
70 if (result < rsize)
71 break;
72 } while (count);
74 memset(buffer, 0, count);
75 flush_dcache_page(page);
76 SetPageUptodate(page);
77 result = 0;
79 io_error:
80 UnlockPage(page);
81 return result;
85 * We are called with the page locked and the caller unlocks.
87 static int
88 smb_readpage(struct file *file, struct page *page)
90 int error;
91 struct dentry *dentry = file->f_dentry;
93 DEBUG1("readpage %p\n", page_address(page));
95 get_page(page);
96 error = smb_readpage_sync(dentry, page);
97 put_page(page);
98 return error;
102 * Write a page synchronously.
103 * Offset is the data offset within the page.
105 static int
106 smb_writepage_sync(struct dentry *dentry, struct page *page,
107 unsigned long offset, unsigned int count)
109 struct inode *inode = dentry->d_inode;
110 u8 *buffer = page_address(page) + offset;
111 int wsize = smb_get_wsize(server_from_dentry(dentry));
112 int result, written = 0;
114 offset += page->index << PAGE_CACHE_SHIFT;
115 VERBOSE("file %s/%s, count=%d@%ld, wsize=%d\n",
116 DENTRY_PATH(dentry), count, offset, wsize);
118 do {
119 if (count < wsize)
120 wsize = count;
122 result = smb_proc_write(dentry, offset, wsize, buffer);
123 if (result < 0)
124 break;
125 /* N.B. what if result < wsize?? */
126 #ifdef SMBFS_PARANOIA
127 if (result < wsize)
128 PARANOIA("short write, wsize=%d, result=%d\n",
129 wsize, result);
130 #endif
131 buffer += wsize;
132 offset += wsize;
133 written += wsize;
134 count -= wsize;
136 * Update the inode now rather than waiting for a refresh.
138 inode->i_mtime = inode->i_atime = CURRENT_TIME;
139 if (offset > inode->i_size)
140 inode->i_size = offset;
141 inode->u.smbfs_i.cache_valid |= SMB_F_LOCALWRITE;
142 } while (count);
143 return written ? written : result;
147 * Write a page to the server. This will be used for NFS swapping only
148 * (for now), and we currently do this synchronously only.
150 * We are called with the page locked and the caller unlocks.
152 static int
153 smb_writepage(struct file *file, struct page *page)
155 struct dentry *dentry = file->f_dentry;
156 struct inode *inode = dentry->d_inode;
157 unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
158 unsigned offset = PAGE_CACHE_SIZE;
159 int err;
161 /* easy case */
162 if (page->index < end_index)
163 goto do_it;
164 /* things got complicated... */
165 offset = inode->i_size & (PAGE_CACHE_SIZE-1);
166 /* OK, are we completely out? */
167 if (page->index >= end_index+1 || !offset)
168 return -EIO;
169 do_it:
170 get_page(page);
171 err = smb_writepage_sync(dentry, page, 0, offset);
172 SetPageUptodate(page);
173 put_page(page);
174 return err;
177 static int
178 smb_updatepage(struct file *file, struct page *page, unsigned long offset,
179 unsigned int count)
181 struct dentry *dentry = file->f_dentry;
183 DEBUG1("(%s/%s %d@%ld)\n", DENTRY_PATH(dentry),
184 count, (page->index << PAGE_CACHE_SHIFT)+offset);
186 return smb_writepage_sync(dentry, page, offset, count);
189 static ssize_t
190 smb_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
192 struct dentry * dentry = file->f_dentry;
193 ssize_t status;
195 VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
196 (unsigned long) count, (unsigned long) *ppos);
198 status = smb_revalidate_inode(dentry);
199 if (status)
201 PARANOIA("%s/%s validation failed, error=%Zd\n",
202 DENTRY_PATH(dentry), status);
203 goto out;
206 VERBOSE("before read, size=%ld, flags=%x, atime=%ld\n",
207 (long)dentry->d_inode->i_size,
208 dentry->d_inode->i_flags, dentry->d_inode->i_atime);
210 status = generic_file_read(file, buf, count, ppos);
211 out:
212 return status;
215 static int
216 smb_file_mmap(struct file * file, struct vm_area_struct * vma)
218 struct dentry * dentry = file->f_dentry;
219 int status;
221 VERBOSE("file %s/%s, address %lu - %lu\n",
222 DENTRY_PATH(dentry), vma->vm_start, vma->vm_end);
224 status = smb_revalidate_inode(dentry);
225 if (status)
227 PARANOIA("%s/%s validation failed, error=%d\n",
228 DENTRY_PATH(dentry), status);
229 goto out;
231 status = generic_file_mmap(file, vma);
232 out:
233 return status;
237 * This does the "real" work of the write. The generic routine has
238 * allocated the page, locked it, done all the page alignment stuff
239 * calculations etc. Now we should just copy the data from user
240 * space and write it back to the real medium..
242 * If the writer ends up delaying the write, the writer needs to
243 * increment the page use counts until he is done with the page.
245 static int smb_prepare_write(struct file *file, struct page *page,
246 unsigned offset, unsigned to)
248 kmap(page);
249 return 0;
252 static int smb_commit_write(struct file *file, struct page *page,
253 unsigned offset, unsigned to)
255 int status;
257 status = -EFAULT;
258 lock_kernel();
259 status = smb_updatepage(file, page, offset, to-offset);
260 unlock_kernel();
261 kunmap(page);
262 return status;
265 struct address_space_operations smb_file_aops = {
266 readpage: smb_readpage,
267 writepage: smb_writepage,
268 prepare_write: smb_prepare_write,
269 commit_write: smb_commit_write
273 * Write to a file (through the page cache).
275 static ssize_t
276 smb_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
278 struct dentry * dentry = file->f_dentry;
279 ssize_t result;
281 VERBOSE("file %s/%s, count=%lu@%lu\n",
282 DENTRY_PATH(dentry),
283 (unsigned long) count, (unsigned long) *ppos);
285 result = smb_revalidate_inode(dentry);
286 if (result)
288 PARANOIA("%s/%s validation failed, error=%Zd\n",
289 DENTRY_PATH(dentry), result);
290 goto out;
293 result = smb_open(dentry, SMB_O_WRONLY);
294 if (result)
295 goto out;
297 if (count > 0)
299 result = generic_file_write(file, buf, count, ppos);
300 VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
301 (long) file->f_pos, (long) dentry->d_inode->i_size,
302 dentry->d_inode->i_mtime, dentry->d_inode->i_atime);
304 out:
305 return result;
308 static int
309 smb_file_open(struct inode *inode, struct file * file)
311 lock_kernel();
312 inode->u.smbfs_i.openers++;
313 unlock_kernel();
314 return 0;
317 static int
318 smb_file_release(struct inode *inode, struct file * file)
320 lock_kernel();
321 if (!--inode->u.smbfs_i.openers)
322 smb_close(inode);
323 unlock_kernel();
324 return 0;
328 * Check whether the required access is compatible with
329 * an inode's permission. SMB doesn't recognize superuser
330 * privileges, so we need our own check for this.
332 static int
333 smb_file_permission(struct inode *inode, int mask)
335 int mode = inode->i_mode;
336 int error = 0;
338 VERBOSE("mode=%x, mask=%x\n", mode, mask);
340 /* Look at user permissions */
341 mode >>= 6;
342 if ((mode & 7 & mask) != mask)
343 error = -EACCES;
344 return error;
347 struct file_operations smb_file_operations =
349 read: smb_file_read,
350 write: smb_file_write,
351 ioctl: smb_ioctl,
352 mmap: smb_file_mmap,
353 open: smb_file_open,
354 release: smb_file_release,
355 fsync: smb_fsync,
358 struct inode_operations smb_file_inode_operations =
360 permission: smb_file_permission,
361 revalidate: smb_revalidate_inode,
362 setattr: smb_notify_change,