file.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/nfs/file.c
  3.  *
  4.  *  Copyright (C) 1992  Rick Sladkey
  5.  *
  6.  *  Changes Copyright (C) 1994 by Florian La Roche
  7.  *   - Do not copy data too often around in the kernel.
  8.  *   - In nfs_file_read the return value of kmalloc wasn't checked.
  9.  *   - Put in a better version of read look-ahead buffering. Original idea
  10.  *     and implementation by Wai S Kok elekokws@ee.nus.sg.
  11.  *
  12.  *  Expire cache on write to a file by Wai S Kok (Oct 1994).
  13.  *
  14.  *  Total rewrite of read side for new NFS buffer cache.. Linus.
  15.  *
  16.  *  nfs regular file handling functions
  17.  */
  18. #include <linux/sched.h>
  19. #include <linux/kernel.h>
  20. #include <linux/errno.h>
  21. #include <linux/fcntl.h>
  22. #include <linux/stat.h>
  23. #include <linux/nfs_fs.h>
  24. #include <linux/nfs_mount.h>
  25. #include <linux/mm.h>
  26. #include <linux/slab.h>
  27. #include <linux/pagemap.h>
  28. #include <linux/lockd/bind.h>
  29. #include <linux/smp_lock.h>
  30. #include <asm/uaccess.h>
  31. #include <asm/system.h>
  32. #define NFSDBG_FACILITY NFSDBG_FILE
  33. static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
  34. static ssize_t nfs_file_read(struct file *, char *, size_t, loff_t *);
  35. static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *);
  36. static int  nfs_file_flush(struct file *);
  37. static int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
  38. struct file_operations nfs_file_operations = {
  39. llseek: generic_file_llseek,
  40. read: nfs_file_read,
  41. write: nfs_file_write,
  42. mmap: nfs_file_mmap,
  43. open: nfs_open,
  44. flush: nfs_file_flush,
  45. release: nfs_release,
  46. fsync: nfs_fsync,
  47. lock: nfs_lock,
  48. };
  49. struct inode_operations nfs_file_inode_operations = {
  50. permission: nfs_permission,
  51. revalidate: nfs_revalidate,
  52. setattr: nfs_notify_change,
  53. };
  54. /* Hack for future NFS swap support */
  55. #ifndef IS_SWAPFILE
  56. # define IS_SWAPFILE(inode) (0)
  57. #endif
  58. /*
  59.  * Flush all dirty pages, and check for write errors.
  60.  *
  61.  */
  62. static int
  63. nfs_file_flush(struct file *file)
  64. {
  65. struct inode *inode = file->f_dentry->d_inode;
  66. int status;
  67. dfprintk(VFS, "nfs: flush(%x/%ld)n", inode->i_dev, inode->i_ino);
  68. /* Make sure all async reads have been sent off. We don't bother
  69.  * waiting on them though... */
  70. if (file->f_mode & FMODE_READ)
  71. nfs_pagein_inode(inode, 0, 0);
  72. status = nfs_wb_file(inode, file);
  73. if (!status) {
  74. status = file->f_error;
  75. file->f_error = 0;
  76. }
  77. return status;
  78. }
  79. static ssize_t
  80. nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
  81. {
  82. struct dentry * dentry = file->f_dentry;
  83. struct inode * inode = dentry->d_inode;
  84. ssize_t result;
  85. dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)n",
  86. dentry->d_parent->d_name.name, dentry->d_name.name,
  87. (unsigned long) count, (unsigned long) *ppos);
  88. result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
  89. if (!result)
  90. result = generic_file_read(file, buf, count, ppos);
  91. return result;
  92. }
  93. static int
  94. nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
  95. {
  96. struct dentry *dentry = file->f_dentry;
  97. struct inode *inode = dentry->d_inode;
  98. int status;
  99. dfprintk(VFS, "nfs: mmap(%s/%s)n",
  100. dentry->d_parent->d_name.name, dentry->d_name.name);
  101. status = nfs_revalidate_inode(NFS_SERVER(inode), inode);
  102. if (!status)
  103. status = generic_file_mmap(file, vma);
  104. return status;
  105. }
  106. /*
  107.  * Flush any dirty pages for this process, and check for write errors.
  108.  * The return status from this call provides a reliable indication of
  109.  * whether any write errors occurred for this process.
  110.  */
  111. static int
  112. nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
  113. {
  114. struct inode *inode = dentry->d_inode;
  115. int status;
  116. dfprintk(VFS, "nfs: fsync(%x/%ld)n", inode->i_dev, inode->i_ino);
  117. lock_kernel();
  118. status = nfs_wb_file(inode, file);
  119. if (!status) {
  120. status = file->f_error;
  121. file->f_error = 0;
  122. }
  123. unlock_kernel();
  124. return status;
  125. }
  126. /*
  127.  * This does the "real" work of the write. The generic routine has
  128.  * allocated the page, locked it, done all the page alignment stuff
  129.  * calculations etc. Now we should just copy the data from user
  130.  * space and write it back to the real medium..
  131.  *
  132.  * If the writer ends up delaying the write, the writer needs to
  133.  * increment the page use counts until he is done with the page.
  134.  */
  135. static int nfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
  136. {
  137. return nfs_flush_incompatible(file, page);
  138. }
  139. static int nfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
  140. {
  141. long status;
  142. lock_kernel();
  143. status = nfs_updatepage(file, page, offset, to-offset);
  144. unlock_kernel();
  145. return status;
  146. }
  147. /*
  148.  * The following is used by wait_on_page(), generic_file_readahead()
  149.  * to initiate the completion of any page readahead operations.
  150.  */
  151. static int nfs_sync_page(struct page *page)
  152. {
  153. struct address_space *mapping;
  154. struct inode *inode;
  155. unsigned long index = page_index(page);
  156. unsigned int rpages;
  157. int result;
  158. mapping = page->mapping;
  159. if (!mapping)
  160. return 0;
  161. inode = mapping->host;
  162. if (!inode)
  163. return 0;
  164. rpages = NFS_SERVER(inode)->rpages;
  165. result = nfs_pagein_inode(inode, index, rpages);
  166. if (result < 0)
  167. return result;
  168. return 0;
  169. }
  170. struct address_space_operations nfs_file_aops = {
  171. readpage: nfs_readpage,
  172. sync_page: nfs_sync_page,
  173. writepage: nfs_writepage,
  174. prepare_write: nfs_prepare_write,
  175. commit_write: nfs_commit_write
  176. };
  177. /* 
  178.  * Write to a file (through the page cache).
  179.  */
  180. static ssize_t
  181. nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
  182. {
  183. struct dentry * dentry = file->f_dentry;
  184. struct inode * inode = dentry->d_inode;
  185. ssize_t result;
  186. dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)n",
  187. dentry->d_parent->d_name.name, dentry->d_name.name,
  188. inode->i_ino, (unsigned long) count, (unsigned long) *ppos);
  189. result = -EBUSY;
  190. if (IS_SWAPFILE(inode))
  191. goto out_swapfile;
  192. result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
  193. if (result)
  194. goto out;
  195. result = count;
  196. if (!count)
  197. goto out;
  198. result = generic_file_write(file, buf, count, ppos);
  199. out:
  200. return result;
  201. out_swapfile:
  202. printk(KERN_INFO "NFS: attempt to write to active swap file!n");
  203. goto out;
  204. }
  205. /*
  206.  * Lock a (portion of) a file
  207.  */
  208. int
  209. nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
  210. {
  211. struct inode * inode = filp->f_dentry->d_inode;
  212. int status = 0;
  213. int status2;
  214. dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%Ld:%Ld)n",
  215. inode->i_dev, inode->i_ino,
  216. fl->fl_type, fl->fl_flags,
  217. (long long)fl->fl_start, (long long)fl->fl_end);
  218. if (!inode)
  219. return -EINVAL;
  220. /* No mandatory locks over NFS */
  221. if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
  222. return -ENOLCK;
  223. /* Fake OK code if mounted without NLM support */
  224. if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) {
  225. if (IS_GETLK(cmd))
  226. status = LOCK_USE_CLNT;
  227. goto out_ok;
  228. }
  229. /*
  230.  * No BSD flocks over NFS allowed.
  231.  * Note: we could try to fake a POSIX lock request here by
  232.  * using ((u32) filp | 0x80000000) or some such as the pid.
  233.  * Not sure whether that would be unique, though, or whether
  234.  * that would break in other places.
  235.  */
  236. if (!fl->fl_owner || (fl->fl_flags & (FL_POSIX|FL_BROKEN)) != FL_POSIX)
  237. return -ENOLCK;
  238. /*
  239.  * Flush all pending writes before doing anything
  240.  * with locks..
  241.  */
  242. status = filemap_fdatasync(inode->i_mapping);
  243. down(&inode->i_sem);
  244. status2 = nfs_wb_all(inode);
  245. if (status2 && !status)
  246. status = status2;
  247. up(&inode->i_sem);
  248. status2 = filemap_fdatawait(inode->i_mapping);
  249. if (status2 && !status)
  250. status = status2;
  251. if (status < 0)
  252. return status;
  253. lock_kernel();
  254. status = nlmclnt_proc(inode, cmd, fl);
  255. unlock_kernel();
  256. if (status < 0)
  257. return status;
  258. status = 0;
  259. /*
  260.  * Make sure we clear the cache whenever we try to get the lock.
  261.  * This makes locking act as a cache coherency point.
  262.  */
  263.  out_ok:
  264. if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
  265. filemap_fdatasync(inode->i_mapping);
  266. down(&inode->i_sem);
  267. nfs_wb_all(inode);      /* we may have slept */
  268. up(&inode->i_sem);
  269. filemap_fdatawait(inode->i_mapping);
  270. nfs_zap_caches(inode);
  271. }
  272. return status;
  273. }