1 /*
2 * file.c
3 *
4 * Copyright (C) 1995, 1996, 1997 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 * Please add a note about your changes to smbfs in the ChangeLog file.
8 */
9
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>
19
20 #include <asm/uaccess.h>
21 #include <asm/system.h>
22
23 #include <linux/smbno.h>
24 #include <linux/smb_fs.h>
25
26 #include "smb_debug.h"
27
28 static int
29 smb_fsync(struct file *file, struct dentry * dentry, int datasync)
30 {
31 VERBOSE("sync file %s/%s\n", DENTRY_PATH(dentry));
32 return 0;
33 }
34
35 /*
36 * Read a page synchronously.
37 */
38 static int
39 smb_readpage_sync(struct dentry *dentry, struct page *page)
40 {
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;
46
47 VERBOSE("file %s/%s, count=%d@%ld, rsize=%d\n",
48 DENTRY_PATH(dentry), count, offset, rsize);
49
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;
55 }
56
57 do {
58 if (count < rsize)
59 rsize = count;
60
61 result = smb_proc_read(dentry->d_inode, offset, rsize, buffer);
62 if (result < 0)
63 goto io_error;
64
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);
72
73 memset(buffer, 0, count);
74 flush_dcache_page(page);
75 SetPageUptodate(page);
76 result = 0;
77
78 io_error:
79 UnlockPage(page);
80 return result;
81 }
82
83 /*
84 * We are called with the page locked and we unlock it when done.
85 */
86 static int
87 smb_readpage(struct file *file, struct page *page)
88 {
89 int error;
90 struct dentry *dentry = file->f_dentry;
91
92 DEBUG1("readpage %p\n", page_address(page));
93
94 get_page(page);
95 error = smb_readpage_sync(dentry, page);
96 put_page(page);
97 return error;
98 }
99
100 /*
101 * Write a page synchronously.
102 * Offset is the data offset within the page.
103 */
104 static int
105 smb_writepage_sync(struct inode *inode, struct page *page,
106 unsigned long offset, unsigned int count)
107 {
108 u8 *buffer = page_address(page) + offset;
109 int wsize = smb_get_wsize(server_from_inode(inode));
110 int result, written = 0;
111
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);
115
116 do {
117 if (count < wsize)
118 wsize = count;
119
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;
125 }
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;
136 /*
137 * Update the inode now rather than waiting for a refresh.
138 */
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;
145 }
146
147 /*
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.
150 *
151 * We are called with the page locked and we unlock it when done.
152 */
153 static int
154 smb_writepage(struct page *page)
155 {
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;
161
162 if (!mapping)
163 BUG();
164 inode = mapping->host;
165 if (!inode)
166 BUG();
167
168 end_index = inode->i_size >> PAGE_CACHE_SHIFT;
169
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;
185 }
186
187 static int
188 smb_updatepage(struct file *file, struct page *page, unsigned long offset,
189 unsigned int count)
190 {
191 struct dentry *dentry = file->f_dentry;
192
193 DEBUG1("(%s/%s %d@%ld)\n", DENTRY_PATH(dentry),
194 count, (page->index << PAGE_CACHE_SHIFT)+offset);
195
196 return smb_writepage_sync(dentry->d_inode, page, offset, count);
197 }
198
199 static ssize_t
200 smb_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
201 {
202 struct dentry * dentry = file->f_dentry;
203 ssize_t status;
204
205 VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
206 (unsigned long) count, (unsigned long) *ppos);
207
208 status = smb_revalidate_inode(dentry);
209 if (status)
210 {
211 PARANOIA("%s/%s validation failed, error=%Zd\n",
212 DENTRY_PATH(dentry), status);
213 goto out;
214 }
215
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);
219
220 status = generic_file_read(file, buf, count, ppos);
221 out:
222 return status;
223 }
224
225 static int
226 smb_file_mmap(struct file * file, struct vm_area_struct * vma)
227 {
228 struct dentry * dentry = file->f_dentry;
229 int status;
230
231 VERBOSE("file %s/%s, address %lu - %lu\n",
232 DENTRY_PATH(dentry), vma->vm_start, vma->vm_end);
233
234 status = smb_revalidate_inode(dentry);
235 if (status)
236 {
237 PARANOIA("%s/%s validation failed, error=%d\n",
238 DENTRY_PATH(dentry), status);
239 goto out;
240 }
241 status = generic_file_mmap(file, vma);
242 out:
243 return status;
244 }
245
246 /*
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..
251 *
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.
254 */
255 static int smb_prepare_write(struct file *file, struct page *page,
256 unsigned offset, unsigned to)
257 {
258 kmap(page);
259 return 0;
260 }
261
262 static int smb_commit_write(struct file *file, struct page *page,
263 unsigned offset, unsigned to)
264 {
265 int status;
266
267 status = -EFAULT;
268 lock_kernel();
269 status = smb_updatepage(file, page, offset, to-offset);
270 unlock_kernel();
271 kunmap(page);
272 return status;
273 }
274
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
280 };
281
282 /*
283 * Write to a file (through the page cache).
284 */
285 static ssize_t
286 smb_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
287 {
288 struct dentry * dentry = file->f_dentry;
289 ssize_t result;
290
291 VERBOSE("file %s/%s, count=%lu@%lu\n",
292 DENTRY_PATH(dentry),
293 (unsigned long) count, (unsigned long) *ppos);
294
295 result = smb_revalidate_inode(dentry);
296 if (result)
297 {
298 PARANOIA("%s/%s validation failed, error=%Zd\n",
299 DENTRY_PATH(dentry), result);
300 goto out;
301 }
302
303 result = smb_open(dentry, SMB_O_WRONLY);
304 if (result)
305 goto out;
306
307 if (count > 0)
308 {
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);
313 }
314 out:
315 return result;
316 }
317
318 static int
319 smb_file_open(struct inode *inode, struct file * file)
320 {
321 int result;
322 struct dentry *dentry = file->f_dentry;
323 int smb_mode = (file->f_mode & O_ACCMODE) - 1;
324
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;
333 }
334
335 static int
336 smb_file_release(struct inode *inode, struct file * file)
337 {
338 lock_kernel();
339 if (!--inode->u.smbfs_i.openers)
340 smb_close(inode);
341 unlock_kernel();
342 return 0;
343 }
344
345 /*
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.
349 */
350 static int
351 smb_file_permission(struct inode *inode, int mask)
352 {
353 int mode = inode->i_mode;
354 int error = 0;
355
356 VERBOSE("mode=%x, mask=%x\n", mode, mask);
357
358 /* Look at user permissions */
359 mode >>= 6;
360 if ((mode & 7 & mask) != mask)
361 error = -EACCES;
362 return error;
363 }
364
365 struct file_operations smb_file_operations =
366 {
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,
374 };
375
376 struct inode_operations smb_file_inode_operations =
377 {
378 permission: smb_file_permission,
379 revalidate: smb_revalidate_inode,
380 setattr: smb_notify_change,
381 };
382
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.