Import 2.3.30pre7
[davej-history.git] / fs / smbfs / file.c
blob189c853f9c1d2e02148cba5dc38b242ff94751cc
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 inline int
30 min(int a, int b)
32 return a < b ? a : b;
35 static int
36 smb_fsync(struct file *file, struct dentry * dentry)
38 #ifdef SMBFS_DEBUG_VERBOSE
39 printk("smb_fsync: sync file %s/%s\n",
40 dentry->d_parent->d_name.name, dentry->d_name.name);
41 #endif
42 return 0;
46 * Read a page synchronously.
48 static int
49 smb_readpage_sync(struct dentry *dentry, struct page *page)
51 char *buffer = (char *) page_address(page);
52 unsigned long offset = page->index << PAGE_CACHE_SHIFT;
53 int rsize = smb_get_rsize(server_from_dentry(dentry));
54 int count = PAGE_SIZE;
55 int result;
57 /* We can't replace this with ClearPageError. why? is it a problem?
58 fs/buffer.c:brw_page does the same. */
59 /* clear_bit(PG_error, &page->flags); */
61 #ifdef SMBFS_DEBUG_VERBOSE
62 printk("smb_readpage_sync: file %s/%s, count=%d@%ld, rsize=%d\n",
63 dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, rsize);
64 #endif
65 result = smb_open(dentry, SMB_O_RDONLY);
66 if (result < 0)
68 #ifdef SMBFS_PARANOIA
69 printk("smb_readpage_sync: %s/%s open failed, error=%d\n",
70 dentry->d_parent->d_name.name, dentry->d_name.name, result);
71 #endif
72 goto io_error;
75 do {
76 if (count < rsize)
77 rsize = count;
79 result = smb_proc_read(dentry, offset, rsize, buffer);
80 if (result < 0)
81 goto io_error;
83 count -= result;
84 offset += result;
85 buffer += result;
86 dentry->d_inode->i_atime = CURRENT_TIME;
87 if (result < rsize)
88 break;
89 } while (count);
91 memset(buffer, 0, count);
92 SetPageUptodate(page);
93 result = 0;
95 io_error:
96 UnlockPage(page);
97 return result;
100 static int
101 smb_readpage(struct dentry *dentry, struct page *page)
103 int error;
105 pr_debug("SMB: smb_readpage %08lx\n", page_address(page));
106 #ifdef SMBFS_PARANOIA
107 if (!PageLocked(page))
108 printk("smb_readpage: page not already locked!\n");
109 #endif
111 get_page(page);
112 error = smb_readpage_sync(dentry, page);
113 put_page(page);
114 return error;
118 * Write a page synchronously.
119 * Offset is the data offset within the page.
121 static int
122 smb_writepage_sync(struct dentry *dentry, struct page *page,
123 unsigned long offset, unsigned int count)
125 struct inode *inode = dentry->d_inode;
126 u8 *buffer = (u8 *) page_address(page) + offset;
127 int wsize = smb_get_wsize(server_from_dentry(dentry));
128 int result, written = 0;
130 offset += page->index << PAGE_CACHE_SHIFT;
131 #ifdef SMBFS_DEBUG_VERBOSE
132 printk("smb_writepage_sync: file %s/%s, count=%d@%ld, wsize=%d\n",
133 dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, wsize);
134 #endif
136 do {
137 if (count < wsize)
138 wsize = count;
140 result = smb_proc_write(dentry, offset, wsize, buffer);
141 if (result < 0)
142 break;
143 /* N.B. what if result < wsize?? */
144 #ifdef SMBFS_PARANOIA
145 if (result < wsize)
146 printk("smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result);
147 #endif
148 buffer += wsize;
149 offset += wsize;
150 written += wsize;
151 count -= wsize;
153 * Update the inode now rather than waiting for a refresh.
155 inode->i_mtime = inode->i_atime = CURRENT_TIME;
156 if (offset > inode->i_size)
157 inode->i_size = offset;
158 inode->u.smbfs_i.cache_valid |= SMB_F_LOCALWRITE;
159 } while (count);
160 return written ? written : result;
164 * Write a page to the server. This will be used for NFS swapping only
165 * (for now), and we currently do this synchronously only.
167 * We are called with the page locked and the caller unlocks.
169 static int
170 smb_writepage(struct dentry *dentry, struct page *page)
172 int result;
174 #ifdef SMBFS_PARANOIA
175 if (!PageLocked(page))
176 printk("smb_writepage: page not already locked!\n");
177 #endif
178 get_page(page);
179 result = smb_writepage_sync(dentry, page, 0, PAGE_SIZE);
180 SetPageUptodate(page);
181 put_page(page);
182 return result;
185 static int
186 smb_updatepage(struct file *file, struct page *page, unsigned long offset, unsigned int count)
188 struct dentry *dentry = file->f_dentry;
190 pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld)\n",
191 dentry->d_parent->d_name.name, dentry->d_name.name,
192 count, (page->index << PAGE_CACHE_SHIFT)+offset);
194 return smb_writepage_sync(dentry, page, offset, count);
197 static ssize_t
198 smb_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
200 struct dentry * dentry = file->f_dentry;
201 ssize_t status;
203 #ifdef SMBFS_DEBUG_VERBOSE
204 printk("smb_file_read: file %s/%s, count=%lu@%lu\n",
205 dentry->d_parent->d_name.name, dentry->d_name.name,
206 (unsigned long) count, (unsigned long) *ppos);
207 #endif
209 status = smb_revalidate_inode(dentry);
210 if (status)
212 #ifdef SMBFS_PARANOIA
213 printk("smb_file_read: %s/%s validation failed, error=%d\n",
214 dentry->d_parent->d_name.name, dentry->d_name.name, status);
215 #endif
216 goto out;
219 #ifdef SMBFS_DEBUG_VERBOSE
220 printk("smb_file_read: before read, size=%ld, pages=%ld, flags=%x, atime=%ld\n",
221 dentry->d_inode->i_size, dentry->d_inode->i_nrpages, dentry->d_inode->i_flags,
222 dentry->d_inode->i_atime);
223 #endif
224 status = generic_file_read(file, buf, count, ppos);
225 out:
226 return status;
229 static int
230 smb_file_mmap(struct file * file, struct vm_area_struct * vma)
232 struct dentry * dentry = file->f_dentry;
233 int status;
235 #ifdef SMBFS_DEBUG_VERBOSE
236 printk("smb_file_mmap: file %s/%s, address %lu - %lu\n",
237 dentry->d_parent->d_name.name, dentry->d_name.name, vma->vm_start, vma->vm_end);
238 #endif
240 status = smb_revalidate_inode(dentry);
241 if (status)
243 #ifdef SMBFS_PARANOIA
244 printk("smb_file_mmap: %s/%s validation failed, error=%d\n",
245 dentry->d_parent->d_name.name, dentry->d_name.name, status);
246 #endif
247 goto out;
249 status = generic_file_mmap(file, vma);
250 out:
251 return status;
255 * This does the "real" work of the write. The generic routine has
256 * allocated the page, locked it, done all the page alignment stuff
257 * calculations etc. Now we should just copy the data from user
258 * space and write it back to the real medium..
260 * If the writer ends up delaying the write, the writer needs to
261 * increment the page use counts until he is done with the page.
263 static int smb_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
265 int status;
267 bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
268 status = -EFAULT;
269 if (bytes) {
270 lock_kernel();
271 status = smb_updatepage(file, page, offset, bytes);
272 unlock_kernel();
274 return status;
278 * Write to a file (through the page cache).
280 static ssize_t
281 smb_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
283 struct dentry * dentry = file->f_dentry;
284 ssize_t result;
286 #ifdef SMBFS_DEBUG_VERBOSE
287 printk("smb_file_write: file %s/%s, count=%lu@%lu, pages=%ld\n",
288 dentry->d_parent->d_name.name, dentry->d_name.name,
289 (unsigned long) count, (unsigned long) *ppos, dentry->d_inode->i_nrpages);
290 #endif
292 result = smb_revalidate_inode(dentry);
293 if (result)
295 #ifdef SMBFS_PARANOIA
296 printk("smb_file_write: %s/%s validation failed, error=%d\n",
297 dentry->d_parent->d_name.name, dentry->d_name.name, result);
298 #endif
299 goto out;
302 result = smb_open(dentry, SMB_O_WRONLY);
303 if (result)
304 goto out;
306 if (count > 0)
308 result = generic_file_write(file, buf, count, ppos, smb_write_one_page);
309 #ifdef SMBFS_DEBUG_VERBOSE
310 printk("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
311 (long) file->f_pos, dentry->d_inode->i_size, dentry->d_inode->i_mtime,
312 dentry->d_inode->i_atime);
313 #endif
315 out:
316 return result;
319 static int
320 smb_file_open(struct inode *inode, struct file * file)
322 #ifdef SMBFS_DEBUG_VERBOSE
323 printk("smb_file_open: opening %s/%s, d_count=%d\n",
324 file->f_dentry->d_parent->d_name.name, file->f_dentry->d_name.name,
325 file->f_dentry->d_count);
326 #endif
327 return 0;
330 static int
331 smb_file_release(struct inode *inode, struct file * file)
333 struct dentry * dentry = file->f_dentry;
335 #ifdef SMBFS_DEBUG_VERBOSE
336 printk("smb_file_release: closing %s/%s, d_count=%d\n",
337 dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
338 #endif
340 if (dentry->d_count == 1)
342 smb_close(inode);
344 return 0;
348 * Check whether the required access is compatible with
349 * an inode's permission. SMB doesn't recognize superuser
350 * privileges, so we need our own check for this.
352 static int
353 smb_file_permission(struct inode *inode, int mask)
355 int mode = inode->i_mode;
356 int error = 0;
358 #ifdef SMBFS_DEBUG_VERBOSE
359 printk("smb_file_permission: mode=%x, mask=%x\n", mode, mask);
360 #endif
361 /* Look at user permissions */
362 mode >>= 6;
363 if ((mode & 7 & mask) != mask)
364 error = -EACCES;
365 return error;
368 static struct file_operations smb_file_operations =
370 NULL, /* lseek - default */
371 smb_file_read, /* read */
372 smb_file_write, /* write */
373 NULL, /* readdir - bad */
374 NULL, /* poll - default */
375 smb_ioctl, /* ioctl */
376 smb_file_mmap, /* mmap(struct file*, struct vm_area_struct*) */
377 smb_file_open, /* open(struct inode*, struct file*) */
378 NULL, /* flush */
379 smb_file_release, /* release(struct inode*, struct file*) */
380 smb_fsync, /* fsync(struct file*, struct dentry*) */
381 NULL, /* fasync(struct file*, int) */
382 NULL, /* check_media_change(kdev_t dev) */
383 NULL, /* revalidate(kdev_t dev) */
384 NULL /* lock(struct file*, int, struct file_lock*) */
387 struct inode_operations smb_file_inode_operations =
389 &smb_file_operations, /* default file operations */
390 NULL, /* create */
391 NULL, /* lookup */
392 NULL, /* link */
393 NULL, /* unlink */
394 NULL, /* symlink */
395 NULL, /* mkdir */
396 NULL, /* rmdir */
397 NULL, /* mknod */
398 NULL, /* rename */
399 NULL, /* readlink */
400 NULL, /* follow_link */
401 NULL, /* get_block */
402 smb_readpage, /* readpage */
403 smb_writepage, /* writepage */
404 NULL, /* truncate */
405 smb_file_permission, /* permission */
406 smb_revalidate_inode, /* revalidate */