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

Linux/Unix编程

开发平台:

Unix_Linux

  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. #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/slab.h>
  16. #include <linux/pagemap.h>
  17. #include <linux/smp_lock.h>
  18. #include <asm/uaccess.h>
  19. #include <asm/system.h>
  20. #include <linux/smbno.h>
  21. #include <linux/smb_fs.h>
  22. #include "smb_debug.h"
  23. #include "proto.h"
  24. static int
  25. smb_fsync(struct file *file, struct dentry * dentry, int datasync)
  26. {
  27. struct smb_sb_info *server = server_from_dentry(dentry);
  28. int result;
  29. VERBOSE("sync file %s/%sn", DENTRY_PATH(dentry));
  30. /*
  31.  * The VFS will writepage() all dirty pages for us, but we
  32.  * should send a SMBflush to the server, letting it know that
  33.  * we want things synchronized with actual storage.
  34.  *
  35.  * Note: this function requires all pages to have been written already
  36.  *       (should be ok with writepage_sync)
  37.  */
  38. smb_lock_server(server);
  39. result = smb_proc_flush(server, dentry->d_inode->u.smbfs_i.fileid);
  40. smb_unlock_server(server);
  41. return result;
  42. }
  43. /*
  44.  * Read a page synchronously.
  45.  */
  46. static int
  47. smb_readpage_sync(struct dentry *dentry, struct page *page)
  48. {
  49. char *buffer = kmap(page);
  50. unsigned long offset = page->index << PAGE_CACHE_SHIFT;
  51. int rsize = smb_get_rsize(server_from_dentry(dentry));
  52. int count = PAGE_SIZE;
  53. int result;
  54. VERBOSE("file %s/%s, count=%d@%ld, rsize=%dn",
  55. DENTRY_PATH(dentry), count, offset, rsize);
  56. result = smb_open(dentry, SMB_O_RDONLY);
  57. if (result < 0) {
  58. PARANOIA("%s/%s open failed, error=%dn",
  59.  DENTRY_PATH(dentry), result);
  60. goto io_error;
  61. }
  62. do {
  63. if (count < rsize)
  64. rsize = count;
  65. result = smb_proc_read(dentry->d_inode, offset, rsize, buffer);
  66. if (result < 0)
  67. goto io_error;
  68. count -= result;
  69. offset += result;
  70. buffer += result;
  71. dentry->d_inode->i_atime = CURRENT_TIME;
  72. if (result < rsize)
  73. break;
  74. } while (count);
  75. memset(buffer, 0, count);
  76. flush_dcache_page(page);
  77. SetPageUptodate(page);
  78. result = 0;
  79. io_error:
  80. kunmap(page);
  81. UnlockPage(page);
  82. return result;
  83. }
  84. /*
  85.  * We are called with the page locked and we unlock it when done.
  86.  */
  87. static int
  88. smb_readpage(struct file *file, struct page *page)
  89. {
  90. int error;
  91. struct dentry  *dentry = file->f_dentry;
  92. get_page(page);
  93. error = smb_readpage_sync(dentry, page);
  94. put_page(page);
  95. return error;
  96. }
  97. /*
  98.  * Write a page synchronously.
  99.  * Offset is the data offset within the page.
  100.  */
  101. static int
  102. smb_writepage_sync(struct inode *inode, struct page *page,
  103.    unsigned long offset, unsigned int count)
  104. {
  105. char *buffer = kmap(page) + offset;
  106. int wsize = smb_get_wsize(server_from_inode(inode));
  107. int result, written = 0;
  108. offset += page->index << PAGE_CACHE_SHIFT;
  109. VERBOSE("file ino=%ld, fileid=%d, count=%d@%ld, wsize=%dn",
  110. inode->i_ino, inode->u.smbfs_i.fileid, count, offset, wsize);
  111. do {
  112. if (count < wsize)
  113. wsize = count;
  114. result = smb_proc_write(inode, offset, wsize, buffer);
  115. if (result < 0) {
  116. PARANOIA("failed write, wsize=%d, result=%dn",
  117.  wsize, result);
  118. break;
  119. }
  120. /* N.B. what if result < wsize?? */
  121. #ifdef SMBFS_PARANOIA
  122. if (result < wsize)
  123. PARANOIA("short write, wsize=%d, result=%dn",
  124.  wsize, result);
  125. #endif
  126. buffer += wsize;
  127. offset += wsize;
  128. written += wsize;
  129. count -= wsize;
  130. /*
  131.  * Update the inode now rather than waiting for a refresh.
  132.  */
  133. inode->i_mtime = inode->i_atime = CURRENT_TIME;
  134. inode->u.smbfs_i.flags |= SMB_F_LOCALWRITE;
  135. if (offset > inode->i_size)
  136. inode->i_size = offset;
  137. } while (count);
  138. kunmap(page);
  139. return written ? written : result;
  140. }
  141. /*
  142.  * Write a page to the server. This will be used for NFS swapping only
  143.  * (for now), and we currently do this synchronously only.
  144.  *
  145.  * We are called with the page locked and we unlock it when done.
  146.  */
  147. static int
  148. smb_writepage(struct page *page)
  149. {
  150. struct address_space *mapping = page->mapping;
  151. struct inode *inode;
  152. unsigned long end_index;
  153. unsigned offset = PAGE_CACHE_SIZE;
  154. int err;
  155. if (!mapping)
  156. BUG();
  157. inode = mapping->host;
  158. if (!inode)
  159. BUG();
  160. end_index = inode->i_size >> PAGE_CACHE_SHIFT;
  161. /* easy case */
  162. if (page->index < end_index)
  163. goto do_it;
  164. /* things got complicated... */
  165. offset = inode->i_size & (PAGE_CACHE_SIZE-1);
  166. /* OK, are we completely out? */
  167. if (page->index >= end_index+1 || !offset)
  168. return -EIO;
  169. do_it:
  170. get_page(page);
  171. err = smb_writepage_sync(inode, page, 0, offset);
  172. SetPageUptodate(page);
  173. UnlockPage(page);
  174. put_page(page);
  175. return err;
  176. }
  177. static int
  178. smb_updatepage(struct file *file, struct page *page, unsigned long offset,
  179.        unsigned int count)
  180. {
  181. struct dentry *dentry = file->f_dentry;
  182. DEBUG1("(%s/%s %d@%ld)n", DENTRY_PATH(dentry), 
  183.        count, (page->index << PAGE_CACHE_SHIFT)+offset);
  184. return smb_writepage_sync(dentry->d_inode, page, offset, count);
  185. }
  186. static ssize_t
  187. smb_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
  188. {
  189. struct dentry * dentry = file->f_dentry;
  190. ssize_t status;
  191. VERBOSE("file %s/%s, count=%lu@%lun", DENTRY_PATH(dentry),
  192. (unsigned long) count, (unsigned long) *ppos);
  193. status = smb_revalidate_inode(dentry);
  194. if (status) {
  195. PARANOIA("%s/%s validation failed, error=%Zdn",
  196.  DENTRY_PATH(dentry), status);
  197. goto out;
  198. }
  199. VERBOSE("before read, size=%ld, flags=%x, atime=%ldn",
  200. (long)dentry->d_inode->i_size,
  201. dentry->d_inode->i_flags, dentry->d_inode->i_atime);
  202. status = generic_file_read(file, buf, count, ppos);
  203. out:
  204. return status;
  205. }
  206. static int
  207. smb_file_mmap(struct file * file, struct vm_area_struct * vma)
  208. {
  209. struct dentry * dentry = file->f_dentry;
  210. int status;
  211. VERBOSE("file %s/%s, address %lu - %lun",
  212. DENTRY_PATH(dentry), vma->vm_start, vma->vm_end);
  213. status = smb_revalidate_inode(dentry);
  214. if (status) {
  215. PARANOIA("%s/%s validation failed, error=%dn",
  216.  DENTRY_PATH(dentry), status);
  217. goto out;
  218. }
  219. status = generic_file_mmap(file, vma);
  220. out:
  221. return status;
  222. }
  223. /*
  224.  * This does the "real" work of the write. The generic routine has
  225.  * allocated the page, locked it, done all the page alignment stuff
  226.  * calculations etc. Now we should just copy the data from user
  227.  * space and write it back to the real medium..
  228.  *
  229.  * If the writer ends up delaying the write, the writer needs to
  230.  * increment the page use counts until he is done with the page.
  231.  */
  232. static int smb_prepare_write(struct file *file, struct page *page, 
  233.      unsigned offset, unsigned to)
  234. {
  235. return 0;
  236. }
  237. static int smb_commit_write(struct file *file, struct page *page,
  238.     unsigned offset, unsigned to)
  239. {
  240. int status;
  241. status = -EFAULT;
  242. lock_kernel();
  243. status = smb_updatepage(file, page, offset, to-offset);
  244. unlock_kernel();
  245. return status;
  246. }
  247. struct address_space_operations smb_file_aops = {
  248. readpage: smb_readpage,
  249. writepage: smb_writepage,
  250. prepare_write: smb_prepare_write,
  251. commit_write: smb_commit_write
  252. };
  253. /* 
  254.  * Write to a file (through the page cache).
  255.  */
  256. static ssize_t
  257. smb_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
  258. {
  259. struct dentry * dentry = file->f_dentry;
  260. ssize_t result;
  261. VERBOSE("file %s/%s, count=%lu@%lun",
  262. DENTRY_PATH(dentry),
  263. (unsigned long) count, (unsigned long) *ppos);
  264. result = smb_revalidate_inode(dentry);
  265. if (result) {
  266. PARANOIA("%s/%s validation failed, error=%Zdn",
  267.  DENTRY_PATH(dentry), result);
  268. goto out;
  269. }
  270. result = smb_open(dentry, SMB_O_WRONLY);
  271. if (result)
  272. goto out;
  273. if (count > 0) {
  274. result = generic_file_write(file, buf, count, ppos);
  275. VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ldn",
  276. (long) file->f_pos, (long) dentry->d_inode->i_size,
  277. dentry->d_inode->i_mtime, dentry->d_inode->i_atime);
  278. }
  279. out:
  280. return result;
  281. }
  282. static int
  283. smb_file_open(struct inode *inode, struct file * file)
  284. {
  285. int result;
  286. struct dentry *dentry = file->f_dentry;
  287. int smb_mode = (file->f_mode & O_ACCMODE) - 1;
  288. lock_kernel();
  289. result = smb_open(dentry, smb_mode);
  290. if (result)
  291. goto out;
  292. inode->u.smbfs_i.openers++;
  293. out:
  294. unlock_kernel();
  295. return 0;
  296. }
  297. static int
  298. smb_file_release(struct inode *inode, struct file * file)
  299. {
  300. lock_kernel();
  301. if (!--inode->u.smbfs_i.openers) {
  302. /* We must flush any dirty pages now as we won't be able to
  303.    write anything after close. mmap can trigger this.
  304.    "openers" should perhaps include mmap'ers ... */
  305. filemap_fdatasync(inode->i_mapping);
  306. filemap_fdatawait(inode->i_mapping);
  307. smb_close(inode);
  308. }
  309. unlock_kernel();
  310. return 0;
  311. }
  312. /*
  313.  * Check whether the required access is compatible with
  314.  * an inode's permission. SMB doesn't recognize superuser
  315.  * privileges, so we need our own check for this.
  316.  */
  317. static int
  318. smb_file_permission(struct inode *inode, int mask)
  319. {
  320. int mode = inode->i_mode;
  321. int error = 0;
  322. VERBOSE("mode=%x, mask=%xn", mode, mask);
  323. /* Look at user permissions */
  324. mode >>= 6;
  325. if ((mode & 7 & mask) != mask)
  326. error = -EACCES;
  327. return error;
  328. }
  329. struct file_operations smb_file_operations =
  330. {
  331. llseek: generic_file_llseek,
  332. read: smb_file_read,
  333. write: smb_file_write,
  334. ioctl: smb_ioctl,
  335. mmap: smb_file_mmap,
  336. open: smb_file_open,
  337. release: smb_file_release,
  338. fsync: smb_fsync,
  339. };
  340. struct inode_operations smb_file_inode_operations =
  341. {
  342. permission: smb_file_permission,
  343. revalidate: smb_revalidate_inode,
  344. setattr: smb_notify_change,
  345. };