- Stephen Rothwell: APM updates
[davej-history.git] / fs / smbfs / file.c
blob79627f8804709bbcc6cf69db44007460c35a5221
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) {
52 PARANOIA("%s/%s open failed, error=%d\n",
53 DENTRY_PATH(dentry), result);
54 goto io_error;
57 do {
58 if (count < rsize)
59 rsize = count;
61 result = smb_proc_read(dentry->d_inode, offset, rsize, buffer);
62 if (result < 0)
63 goto io_error;
65 count -= result;
66 offset += result;
67 buffer += result;
68 dentry->d_inode->i_atime = CURRENT_TIME;
69 if (result < rsize)
70 break;
71 } while (count);
73 memset(buffer, 0, count);
74 flush_dcache_page(page);
75 SetPageUptodate(page);
76 result = 0;
78 io_error:
79 UnlockPage(page);
80 return result;
84 * We are called with the page locked and we unlock it when done.
86 static int
87 smb_readpage(struct file *file, struct page *page)
89 int error;
90 struct dentry *dentry = file->f_dentry;
92 DEBUG1("readpage %p\n", page_address(page));
94 get_page(page);
95 error = smb_readpage_sync(dentry, page);
96 put_page(page);
97 return error;
101 * Write a page synchronously.
102 * Offset is the data offset within the page.
104 static int
105 smb_writepage_sync(struct inode *inode, struct page *page,
106 unsigned long offset, unsigned int count)
108 u8 *buffer = page_address(page) + offset;
109 int wsize = smb_get_wsize(server_from_inode(inode));
110 int result, written = 0;
112 offset += page->index << PAGE_CACHE_SHIFT;
113 VERBOSE("file ino=%ld, fileid=%d, count=%d@%ld, wsize=%d\n",
114 inode->i_ino, inode->u.smbfs_i.fileid, count, offset, wsize);
116 do {
117 if (count < wsize)
118 wsize = count;
120 result = smb_proc_write(inode, offset, wsize, buffer);
121 if (result < 0) {
122 PARANOIA("failed write, wsize=%d, result=%d\n",
123 wsize, result);
124 break;
126 /* N.B. what if result < wsize?? */
127 #ifdef SMBFS_PARANOIA
128 if (result < wsize)
129 PARANOIA("short write, wsize=%d, result=%d\n",
130 wsize, result);
131 #endif
132 buffer += wsize;
133 offset += wsize;
134 written += wsize;
135 count -= wsize;
137 * Update the inode now rather than waiting for a refresh.
139 inode->i_mtime = inode->i_atime = CURRENT_TIME;
140 if (offset > inode->i_size)
141 inode->i_size = offset;
142 inode->u.smbfs_i.cache_valid |= SMB_F_LOCALWRITE;
143 } while (count);
144 return written ? written : result;
148 * Write a page to the server. This will be used for NFS swapping only
149 * (for now), and we currently do this synchronously only.
151 * We are called with the page locked and we unlock it when done.
153 static int
154 smb_writepage(struct page *page)
156 struct address_space *mapping = page->mapping;
157 struct inode *inode;
158 unsigned long end_index;
159 unsigned offset = PAGE_CACHE_SIZE;
160 int err;
162 if (!mapping)
163 BUG();
164 inode = (struct inode *)mapping->host;
165 if (!inode)
166 BUG();
168 end_index = inode->i_size >> PAGE_CACHE_SHIFT;
170 /* easy case */
171 if (page->index < end_index)
172 goto do_it;
173 /* things got complicated... */
174 offset = inode->i_size & (PAGE_CACHE_SIZE-1);
175 /* OK, are we completely out? */
176 if (page->index >= end_index+1 || !offset)
177 return -EIO;
178 do_it:
179 get_page(page);
180 err = smb_writepage_sync(inode, page, 0, offset);
181 SetPageUptodate(page);
182 UnlockPage(page);
183 put_page(page);
184 return err;
187 static int
188 smb_updatepage(struct file *file, struct page *page, unsigned long offset,
189 unsigned int count)
191 struct dentry *dentry = file->f_dentry;
193 DEBUG1("(%s/%s %d@%ld)\n", DENTRY_PATH(dentry),
194 count, (page->index << PAGE_CACHE_SHIFT)+offset);
196 return smb_writepage_sync(dentry->d_inode, page, offset, count);
199 static ssize_t
200 smb_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
202 struct dentry * dentry = file->f_dentry;
203 ssize_t status;
205 VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
206 (unsigned long) count, (unsigned long) *ppos);
208 status = smb_revalidate_inode(dentry);
209 if (status)
211 PARANOIA("%s/%s validation failed, error=%Zd\n",
212 DENTRY_PATH(dentry), status);
213 goto out;
216 VERBOSE("before read, size=%ld, flags=%x, atime=%ld\n",
217 (long)dentry->d_inode->i_size,
218 dentry->d_inode->i_flags, dentry->d_inode->i_atime);
220 status = generic_file_read(file, buf, count, ppos);
221 out:
222 return status;
225 static int
226 smb_file_mmap(struct file * file, struct vm_area_struct * vma)
228 struct dentry * dentry = file->f_dentry;
229 int status;
231 VERBOSE("file %s/%s, address %lu - %lu\n",
232 DENTRY_PATH(dentry), vma->vm_start, vma->vm_end);
234 status = smb_revalidate_inode(dentry);
235 if (status)
237 PARANOIA("%s/%s validation failed, error=%d\n",
238 DENTRY_PATH(dentry), status);
239 goto out;
241 status = generic_file_mmap(file, vma);
242 out:
243 return status;
247 * This does the "real" work of the write. The generic routine has
248 * allocated the page, locked it, done all the page alignment stuff
249 * calculations etc. Now we should just copy the data from user
250 * space and write it back to the real medium..
252 * If the writer ends up delaying the write, the writer needs to
253 * increment the page use counts until he is done with the page.
255 static int smb_prepare_write(struct file *file, struct page *page,
256 unsigned offset, unsigned to)
258 kmap(page);
259 return 0;
262 static int smb_commit_write(struct file *file, struct page *page,
263 unsigned offset, unsigned to)
265 int status;
267 status = -EFAULT;
268 lock_kernel();
269 status = smb_updatepage(file, page, offset, to-offset);
270 unlock_kernel();
271 kunmap(page);
272 return status;
275 struct address_space_operations smb_file_aops = {
276 readpage: smb_readpage,
277 writepage: smb_writepage,
278 prepare_write: smb_prepare_write,
279 commit_write: smb_commit_write
283 * Write to a file (through the page cache).
285 static ssize_t
286 smb_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
288 struct dentry * dentry = file->f_dentry;
289 ssize_t result;
291 VERBOSE("file %s/%s, count=%lu@%lu\n",
292 DENTRY_PATH(dentry),
293 (unsigned long) count, (unsigned long) *ppos);
295 result = smb_revalidate_inode(dentry);
296 if (result)
298 PARANOIA("%s/%s validation failed, error=%Zd\n",
299 DENTRY_PATH(dentry), result);
300 goto out;
303 result = smb_open(dentry, SMB_O_WRONLY);
304 if (result)
305 goto out;
307 if (count > 0)
309 result = generic_file_write(file, buf, count, ppos);
310 VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
311 (long) file->f_pos, (long) dentry->d_inode->i_size,
312 dentry->d_inode->i_mtime, dentry->d_inode->i_atime);
314 out:
315 return result;
318 static int
319 smb_file_open(struct inode *inode, struct file * file)
321 int result;
322 struct dentry *dentry = file->f_dentry;
323 int smb_mode = (file->f_mode & O_ACCMODE) - 1;
325 lock_kernel();
326 result = smb_open(dentry, smb_mode);
327 if (result)
328 goto out;
329 inode->u.smbfs_i.openers++;
330 out:
331 unlock_kernel();
332 return 0;
335 static int
336 smb_file_release(struct inode *inode, struct file * file)
338 lock_kernel();
339 if (!--inode->u.smbfs_i.openers)
340 smb_close(inode);
341 unlock_kernel();
342 return 0;
346 * Check whether the required access is compatible with
347 * an inode's permission. SMB doesn't recognize superuser
348 * privileges, so we need our own check for this.
350 static int
351 smb_file_permission(struct inode *inode, int mask)
353 int mode = inode->i_mode;
354 int error = 0;
356 VERBOSE("mode=%x, mask=%x\n", mode, mask);
358 /* Look at user permissions */
359 mode >>= 6;
360 if ((mode & 7 & mask) != mask)
361 error = -EACCES;
362 return error;
365 struct file_operations smb_file_operations =
367 read: smb_file_read,
368 write: smb_file_write,
369 ioctl: smb_ioctl,
370 mmap: smb_file_mmap,
371 open: smb_file_open,
372 release: smb_file_release,
373 fsync: smb_fsync,
376 struct inode_operations smb_file_inode_operations =
378 permission: smb_file_permission,
379 revalidate: smb_revalidate_inode,
380 setattr: smb_notify_change,