symlink.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:2k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/nfs/symlink.c
  3.  *
  4.  *  Copyright (C) 1992  Rick Sladkey
  5.  *
  6.  *  Optimization changes Copyright (C) 1994 Florian La Roche
  7.  *
  8.  *  Jun 7 1999, cache symlink lookups in the page cache.  -DaveM
  9.  *
  10.  *  nfs symlink handling code
  11.  */
  12. #define NFS_NEED_XDR_TYPES
  13. #include <linux/sched.h>
  14. #include <linux/errno.h>
  15. #include <linux/sunrpc/clnt.h>
  16. #include <linux/nfs.h>
  17. #include <linux/nfs2.h>
  18. #include <linux/nfs_fs.h>
  19. #include <linux/pagemap.h>
  20. #include <linux/stat.h>
  21. #include <linux/mm.h>
  22. #include <linux/slab.h>
  23. #include <linux/string.h>
  24. #include <linux/smp_lock.h>
  25. /* Symlink caching in the page cache is even more simplistic
  26.  * and straight-forward than readdir caching.
  27.  */
  28. static int nfs_symlink_filler(struct inode *inode, struct page *page)
  29. {
  30. void *buffer = kmap(page);
  31. int error;
  32. /* We place the length at the beginning of the page,
  33.  * in host byte order, followed by the string.  The
  34.  * XDR response verification will NULL terminate it.
  35.  */
  36. lock_kernel();
  37. error = NFS_PROTO(inode)->readlink(inode, buffer,
  38.    PAGE_CACHE_SIZE - sizeof(u32)-4);
  39. unlock_kernel();
  40. if (error < 0)
  41. goto error;
  42. SetPageUptodate(page);
  43. kunmap(page);
  44. UnlockPage(page);
  45. return 0;
  46. error:
  47. SetPageError(page);
  48. kunmap(page);
  49. UnlockPage(page);
  50. return -EIO;
  51. }
  52. static char *nfs_getlink(struct inode *inode, struct page **ppage)
  53. {
  54. struct page *page;
  55. u32 *p;
  56. /* Caller revalidated the directory inode already. */
  57. page = read_cache_page(&inode->i_data, 0,
  58. (filler_t *)nfs_symlink_filler, inode);
  59. if (IS_ERR(page))
  60. goto read_failed;
  61. if (!Page_Uptodate(page))
  62. goto getlink_read_error;
  63. *ppage = page;
  64. p = kmap(page);
  65. return (char*)(p+1);
  66. getlink_read_error:
  67. page_cache_release(page);
  68. return ERR_PTR(-EIO);
  69. read_failed:
  70. return (char*)page;
  71. }
  72. static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
  73. {
  74. struct inode *inode = dentry->d_inode;
  75. struct page *page = NULL;
  76. int res = vfs_readlink(dentry,buffer,buflen,nfs_getlink(inode,&page));
  77. if (page) {
  78. kunmap(page);
  79. page_cache_release(page);
  80. }
  81. return res;
  82. }
  83. static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
  84. {
  85. struct inode *inode = dentry->d_inode;
  86. struct page *page = NULL;
  87. int res = vfs_follow_link(nd, nfs_getlink(inode,&page));
  88. if (page) {
  89. kunmap(page);
  90. page_cache_release(page);
  91. }
  92. return res;
  93. }
  94. /*
  95.  * symlinks can't do much...
  96.  */
  97. struct inode_operations nfs_symlink_inode_operations = {
  98. readlink: nfs_readlink,
  99. follow_link: nfs_follow_link,
  100. revalidate: nfs_revalidate,
  101. setattr: nfs_notify_change,
  102. };