Merge with 2.3.99-pre9.
[linux-2.6/linux-mips.git] / fs / smbfs / file.c
blobb47e236b0ee41d72d2badaea20d0109de8f98128
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 */
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/fcntl.h>
13 #include <linux/stat.h>
14 #include <linux/mm.h>
15 #include <linux/malloc.h>
16 #include <linux/pagemap.h>
17 #include <linux/smp_lock.h>
19 #include <asm/uaccess.h>
20 #include <asm/system.h>
22 #include <linux/smbno.h>
23 #include <linux/smb_fs.h>
25 #define SMBFS_PARANOIA 1
26 /* #define SMBFS_DEBUG_VERBOSE 1 */
27 /* #define pr_debug printk */
29 static int
30 smb_fsync(struct file *file, struct dentry * dentry)
32 #ifdef SMBFS_DEBUG_VERBOSE
33 printk("smb_fsync: sync file %s/%s\n",
34 dentry->d_parent->d_name.name, dentry->d_name.name);
35 #endif
36 return 0;
40 * Read a page synchronously.
42 static int
43 smb_readpage_sync(struct dentry *dentry, struct page *page)
45 char *buffer = (char *) page_address(page);
46 unsigned long offset = page->index << PAGE_CACHE_SHIFT;
47 int rsize = smb_get_rsize(server_from_dentry(dentry));
48 int count = PAGE_SIZE;
49 int result;
51 /* We can't replace this with ClearPageError. why? is it a problem?
52 fs/buffer.c:brw_page does the same. */
53 /* ClearPageError(page); */
55 #ifdef SMBFS_DEBUG_VERBOSE
56 printk("smb_readpage_sync: file %s/%s, count=%d@%ld, rsize=%d\n",
57 dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, rsize);
58 #endif
59 result = smb_open(dentry, SMB_O_RDONLY);
60 if (result < 0)
62 #ifdef SMBFS_PARANOIA
63 printk("smb_readpage_sync: %s/%s open failed, error=%d\n",
64 dentry->d_parent->d_name.name, dentry->d_name.name, result);
65 #endif
66 goto io_error;
69 do {
70 if (count < rsize)
71 rsize = count;
73 result = smb_proc_read(dentry, offset, rsize, buffer);
74 if (result < 0)
75 goto io_error;
77 count -= result;
78 offset += result;
79 buffer += result;
80 dentry->d_inode->i_atime = CURRENT_TIME;
81 if (result < rsize)
82 break;
83 } while (count);
85 memset(buffer, 0, count);
86 SetPageUptodate(page);
87 result = 0;
89 io_error:
90 UnlockPage(page);
91 return result;
94 static int
95 smb_readpage(struct file *file, struct page *page)
97 int error;
98 struct dentry *dentry = file->f_dentry;
100 pr_debug("SMB: smb_readpage %08lx\n", page_address(page));
101 #ifdef SMBFS_PARANOIA
102 if (!PageLocked(page))
103 printk("smb_readpage: page not already locked!\n");
104 #endif
106 get_page(page);
107 error = smb_readpage_sync(dentry, page);
108 put_page(page);
109 return error;
113 * Write a page synchronously.
114 * Offset is the data offset within the page.
116 static int
117 smb_writepage_sync(struct dentry *dentry, struct page *page,
118 unsigned long offset, unsigned int count)
120 struct inode *inode = dentry->d_inode;
121 u8 *buffer = (u8 *) page_address(page) + offset;
122 int wsize = smb_get_wsize(server_from_dentry(dentry));
123 int result, written = 0;
125 offset += page->index << PAGE_CACHE_SHIFT;
126 #ifdef SMBFS_DEBUG_VERBOSE
127 printk("smb_writepage_sync: file %s/%s, count=%d@%ld, wsize=%d\n",
128 dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, wsize);
129 #endif
131 do {
132 if (count < wsize)
133 wsize = count;
135 result = smb_proc_write(dentry, offset, wsize, buffer);
136 if (result < 0)
137 break;
138 /* N.B. what if result < wsize?? */
139 #ifdef SMBFS_PARANOIA
140 if (result < wsize)
141 printk("smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result);
142 #endif
143 buffer += wsize;
144 offset += wsize;
145 written += wsize;
146 count -= wsize;
148 * Update the inode now rather than waiting for a refresh.
150 inode->i_mtime = inode->i_atime = CURRENT_TIME;
151 if (offset > inode->i_size)
152 inode->i_size = offset;
153 inode->u.smbfs_i.cache_valid |= SMB_F_LOCALWRITE;
154 } while (count);
155 return written ? written : result;
159 * Write a page to the server. This will be used for NFS swapping only
160 * (for now), and we currently do this synchronously only.
162 * We are called with the page locked and the caller unlocks.
164 static int
165 smb_writepage(struct file *file, struct page *page)
167 struct dentry *dentry = file->f_dentry;
168 struct inode *inode = dentry->d_inode;
169 unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
170 unsigned offset = PAGE_CACHE_SIZE;
171 int err;
173 /* easy case */
174 if (page->index < end_index)
175 goto do_it;
176 /* things got complicated... */
177 offset = inode->i_size & (PAGE_CACHE_SIZE-1);
178 /* OK, are we completely out? */
179 if (page->index >= end_index+1 || !offset)
180 return -EIO;
181 do_it:
182 get_page(page);
183 err = smb_writepage_sync(dentry, page, 0, offset);
184 SetPageUptodate(page);
185 put_page(page);
186 return err;
189 static int
190 smb_updatepage(struct file *file, struct page *page, unsigned long offset, unsigned int count)
192 struct dentry *dentry = file->f_dentry;
194 pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld)\n",
195 dentry->d_parent->d_name.name, dentry->d_name.name,
196 count, (page->index << PAGE_CACHE_SHIFT)+offset);
198 return smb_writepage_sync(dentry, page, offset, count);
201 static ssize_t
202 smb_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
204 struct dentry * dentry = file->f_dentry;
205 ssize_t status;
207 #ifdef SMBFS_DEBUG_VERBOSE
208 printk("smb_file_read: file %s/%s, count=%lu@%lu\n",
209 dentry->d_parent->d_name.name, dentry->d_name.name,
210 (unsigned long) count, (unsigned long) *ppos);
211 #endif
213 status = smb_revalidate_inode(dentry);
214 if (status)
216 #ifdef SMBFS_PARANOIA
217 printk("smb_file_read: %s/%s validation failed, error=%d\n",
218 dentry->d_parent->d_name.name, dentry->d_name.name, status);
219 #endif
220 goto out;
223 #ifdef SMBFS_DEBUG_VERBOSE
224 printk("smb_file_read: before read, size=%ld, pages=%ld, flags=%x, atime=%ld\n",
225 dentry->d_inode->i_size, dentry->d_inode->i_nrpages, dentry->d_inode->i_flags,
226 dentry->d_inode->i_atime);
227 #endif
228 status = generic_file_read(file, buf, count, ppos);
229 out:
230 return status;
233 static int
234 smb_file_mmap(struct file * file, struct vm_area_struct * vma)
236 struct dentry * dentry = file->f_dentry;
237 int status;
239 #ifdef SMBFS_DEBUG_VERBOSE
240 printk("smb_file_mmap: file %s/%s, address %lu - %lu\n",
241 dentry->d_parent->d_name.name, dentry->d_name.name, vma->vm_start, vma->vm_end);
242 #endif
244 status = smb_revalidate_inode(dentry);
245 if (status)
247 #ifdef SMBFS_PARANOIA
248 printk("smb_file_mmap: %s/%s validation failed, error=%d\n",
249 dentry->d_parent->d_name.name, dentry->d_name.name, status);
250 #endif
251 goto out;
253 status = generic_file_mmap(file, vma);
254 out:
255 return status;
259 * This does the "real" work of the write. The generic routine has
260 * allocated the page, locked it, done all the page alignment stuff
261 * calculations etc. Now we should just copy the data from user
262 * space and write it back to the real medium..
264 * If the writer ends up delaying the write, the writer needs to
265 * increment the page use counts until he is done with the page.
267 static int smb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
269 kmap(page);
270 return 0;
273 static int smb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
275 int status;
277 status = -EFAULT;
278 lock_kernel();
279 status = smb_updatepage(file, page, offset, to-offset);
280 unlock_kernel();
281 kunmap(page);
282 return status;
285 struct address_space_operations smb_file_aops = {
286 readpage: smb_readpage,
287 writepage: smb_writepage,
288 prepare_write: smb_prepare_write,
289 commit_write: smb_commit_write
293 * Write to a file (through the page cache).
295 static ssize_t
296 smb_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
298 struct dentry * dentry = file->f_dentry;
299 ssize_t result;
301 #ifdef SMBFS_DEBUG_VERBOSE
302 printk("smb_file_write: file %s/%s, count=%lu@%lu, pages=%ld\n",
303 dentry->d_parent->d_name.name, dentry->d_name.name,
304 (unsigned long) count, (unsigned long) *ppos, dentry->d_inode->i_nrpages);
305 #endif
307 result = smb_revalidate_inode(dentry);
308 if (result)
310 #ifdef SMBFS_PARANOIA
311 printk("smb_file_write: %s/%s validation failed, error=%d\n",
312 dentry->d_parent->d_name.name, dentry->d_name.name, result);
313 #endif
314 goto out;
317 result = smb_open(dentry, SMB_O_WRONLY);
318 if (result)
319 goto out;
321 if (count > 0)
323 result = generic_file_write(file, buf, count, ppos);
324 #ifdef SMBFS_DEBUG_VERBOSE
325 printk("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
326 (long) file->f_pos, dentry->d_inode->i_size, dentry->d_inode->i_mtime,
327 dentry->d_inode->i_atime);
328 #endif
330 out:
331 return result;
334 static int
335 smb_file_open(struct inode *inode, struct file * file)
337 inode->u.smbfs_i.openers++;
338 return 0;
341 static int
342 smb_file_release(struct inode *inode, struct file * file)
344 if (!--inode->u.smbfs_i.openers)
345 smb_close(inode);
346 return 0;
350 * Check whether the required access is compatible with
351 * an inode's permission. SMB doesn't recognize superuser
352 * privileges, so we need our own check for this.
354 static int
355 smb_file_permission(struct inode *inode, int mask)
357 int mode = inode->i_mode;
358 int error = 0;
360 #ifdef SMBFS_DEBUG_VERBOSE
361 printk("smb_file_permission: mode=%x, mask=%x\n", mode, mask);
362 #endif
363 /* Look at user permissions */
364 mode >>= 6;
365 if ((mode & 7 & mask) != mask)
366 error = -EACCES;
367 return error;
370 struct file_operations smb_file_operations =
372 read: smb_file_read,
373 write: smb_file_write,
374 ioctl: smb_ioctl,
375 mmap: smb_file_mmap,
376 open: smb_file_open,
377 release: smb_file_release,
378 fsync: smb_fsync,
381 struct inode_operations smb_file_inode_operations =
383 permission: smb_file_permission,
384 revalidate: smb_revalidate_inode,
385 setattr: smb_notify_change,