cache.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * cache.c
  3. *
  4. * Copyright (C) 1997 by Bill Hawes
  5. *
  6. * Routines to support directory cacheing using the page cache.
  7. * This cache code is almost directly taken from ncpfs.
  8. *
  9. * Please add a note about your changes to smbfs in the ChangeLog file.
  10. */
  11. #include <linux/time.h>
  12. #include <linux/errno.h>
  13. #include <linux/kernel.h>
  14. #include <linux/mm.h>
  15. #include <linux/dirent.h>
  16. #include <linux/smb_fs.h>
  17. #include <linux/pagemap.h>
  18. #include <linux/net.h>
  19. #include <asm/page.h>
  20. #include "smb_debug.h"
  21. #include "proto.h"
  22. /*
  23. * Force the next attempt to use the cache to be a timeout.
  24. * If we can't find the page that's fine, it will cause a refresh.
  25. */
  26. void
  27. smb_invalid_dir_cache(struct inode * dir)
  28. {
  29. struct smb_sb_info *server = server_from_inode(dir);
  30. union smb_dir_cache *cache = NULL;
  31. struct page *page = NULL;
  32. page = grab_cache_page(&dir->i_data, 0);
  33. if (!page)
  34. goto out;
  35. if (!PageUptodate(page))
  36. goto out_unlock;
  37. cache = kmap(page);
  38. cache->head.time = jiffies - SMB_MAX_AGE(server);
  39. kunmap(page);
  40. SetPageUptodate(page);
  41. out_unlock:
  42. unlock_page(page);
  43. page_cache_release(page);
  44. out:
  45. return;
  46. }
  47. /*
  48. * Mark all dentries for 'parent' as invalid, forcing them to be re-read
  49. */
  50. void
  51. smb_invalidate_dircache_entries(struct dentry *parent)
  52. {
  53. struct smb_sb_info *server = server_from_dentry(parent);
  54. struct list_head *next;
  55. struct dentry *dentry;
  56. spin_lock(&dcache_lock);
  57. next = parent->d_subdirs.next;
  58. while (next != &parent->d_subdirs) {
  59. dentry = list_entry(next, struct dentry, d_u.d_child);
  60. dentry->d_fsdata = NULL;
  61. smb_age_dentry(server, dentry);
  62. next = next->next;
  63. }
  64. spin_unlock(&dcache_lock);
  65. }
  66. /*
  67. * dget, but require that fpos and parent matches what the dentry contains.
  68. * dentry is not known to be a valid pointer at entry.
  69. */
  70. struct dentry *
  71. smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
  72. {
  73. struct dentry *dent = dentry;
  74. struct list_head *next;
  75. if (d_validate(dent, parent)) {
  76. if (dent->d_name.len <= SMB_MAXNAMELEN &&
  77. (unsigned long)dent->d_fsdata == fpos) {
  78. if (!dent->d_inode) {
  79. dput(dent);
  80. dent = NULL;
  81. }
  82. return dent;
  83. }
  84. dput(dent);
  85. }
  86. /* If a pointer is invalid, we search the dentry. */
  87. spin_lock(&dcache_lock);
  88. next = parent->d_subdirs.next;
  89. while (next != &parent->d_subdirs) {
  90. dent = list_entry(next, struct dentry, d_u.d_child);
  91. if ((unsigned long)dent->d_fsdata == fpos) {
  92. if (dent->d_inode)
  93. dget_locked(dent);
  94. else
  95. dent = NULL;
  96. goto out_unlock;
  97. }
  98. next = next->next;
  99. }
  100. dent = NULL;
  101. out_unlock:
  102. spin_unlock(&dcache_lock);
  103. return dent;
  104. }
  105. /*
  106. * Create dentry/inode for this file and add it to the dircache.
  107. */
  108. int
  109. smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
  110. struct smb_cache_control *ctrl, struct qstr *qname,
  111. struct smb_fattr *entry)
  112. {
  113. struct dentry *newdent, *dentry = filp->f_path.dentry;
  114. struct inode *newino, *inode = dentry->d_inode;
  115. struct smb_cache_control ctl = *ctrl;
  116. int valid = 0;
  117. int hashed = 0;
  118. ino_t ino = 0;
  119. qname->hash = full_name_hash(qname->name, qname->len);
  120. if (dentry->d_op && dentry->d_op->d_hash)
  121. if (dentry->d_op->d_hash(dentry, qname) != 0)
  122. goto end_advance;
  123. newdent = d_lookup(dentry, qname);
  124. if (!newdent) {
  125. newdent = d_alloc(dentry, qname);
  126. if (!newdent)
  127. goto end_advance;
  128. } else {
  129. hashed = 1;
  130. memcpy((char *) newdent->d_name.name, qname->name,
  131. newdent->d_name.len);
  132. }
  133. if (!newdent->d_inode) {
  134. smb_renew_times(newdent);
  135. entry->f_ino = iunique(inode->i_sb, 2);
  136. newino = smb_iget(inode->i_sb, entry);
  137. if (newino) {
  138. smb_new_dentry(newdent);
  139. d_instantiate(newdent, newino);
  140. if (!hashed)
  141. d_rehash(newdent);
  142. }
  143. } else
  144. smb_set_inode_attr(newdent->d_inode, entry);
  145. if (newdent->d_inode) {
  146. ino = newdent->d_inode->i_ino;
  147. newdent->d_fsdata = (void *) ctl.fpos;
  148. smb_new_dentry(newdent);
  149. }
  150. if (ctl.idx >= SMB_DIRCACHE_SIZE) {
  151. if (ctl.page) {
  152. kunmap(ctl.page);
  153. SetPageUptodate(ctl.page);
  154. unlock_page(ctl.page);
  155. page_cache_release(ctl.page);
  156. }
  157. ctl.cache = NULL;
  158. ctl.idx -= SMB_DIRCACHE_SIZE;
  159. ctl.ofs += 1;
  160. ctl.page = grab_cache_page(&inode->i_data, ctl.ofs);
  161. if (ctl.page)
  162. ctl.cache = kmap(ctl.page);
  163. }
  164. if (ctl.cache) {
  165. ctl.cache->dentry[ctl.idx] = newdent;
  166. valid = 1;
  167. }
  168. dput(newdent);
  169. end_advance:
  170. if (!valid)
  171. ctl.valid = 0;
  172. if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
  173. if (!ino)
  174. ino = find_inode_number(dentry, qname);
  175. if (!ino)
  176. ino = iunique(inode->i_sb, 2);
  177. ctl.filled = filldir(dirent, qname->name, qname->len,
  178. filp->f_pos, ino, DT_UNKNOWN);
  179. if (!ctl.filled)
  180. filp->f_pos += 1;
  181. }
  182. ctl.fpos += 1;
  183. ctl.idx += 1;
  184. *ctrl = ctl;
  185. return (ctl.valid || !ctl.filled);
  186. }