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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  dir.c
  3.  *
  4.  *  Copyright (C) 1995, 1996 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/errno.h>
  11. #include <linux/kernel.h>
  12. #include <linux/smp_lock.h>
  13. #include <linux/ctype.h>
  14. #include <linux/smb_fs.h>
  15. #include <linux/smb_mount.h>
  16. #include <linux/smbno.h>
  17. #include "smb_debug.h"
  18. #include "proto.h"
  19. static int smb_readdir(struct file *, void *, filldir_t);
  20. static int smb_dir_open(struct inode *, struct file *);
  21. static struct dentry *smb_lookup(struct inode *, struct dentry *);
  22. static int smb_create(struct inode *, struct dentry *, int);
  23. static int smb_mkdir(struct inode *, struct dentry *, int);
  24. static int smb_rmdir(struct inode *, struct dentry *);
  25. static int smb_unlink(struct inode *, struct dentry *);
  26. static int smb_rename(struct inode *, struct dentry *,
  27.       struct inode *, struct dentry *);
  28. struct file_operations smb_dir_operations =
  29. {
  30. read: generic_read_dir,
  31. readdir: smb_readdir,
  32. ioctl: smb_ioctl,
  33. open: smb_dir_open,
  34. };
  35. struct inode_operations smb_dir_inode_operations =
  36. {
  37. create: smb_create,
  38. lookup: smb_lookup,
  39. unlink: smb_unlink,
  40. mkdir: smb_mkdir,
  41. rmdir: smb_rmdir,
  42. rename: smb_rename,
  43. revalidate: smb_revalidate_inode,
  44. setattr: smb_notify_change,
  45. };
  46. /*
  47.  * Read a directory, using filldir to fill the dirent memory.
  48.  * smb_proc_readdir does the actual reading from the smb server.
  49.  *
  50.  * The cache code is almost directly taken from ncpfs
  51.  */
  52. static int 
  53. smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
  54. {
  55. struct dentry *dentry = filp->f_dentry;
  56. struct inode *dir = dentry->d_inode;
  57. struct smb_sb_info *server = server_from_dentry(dentry);
  58. union  smb_dir_cache *cache = NULL;
  59. struct smb_cache_control ctl;
  60. struct page *page = NULL;
  61. int result;
  62. ctl.page  = NULL;
  63. ctl.cache = NULL;
  64. VERBOSE("reading %s/%s, f_pos=%dn",
  65. DENTRY_PATH(dentry),  (int) filp->f_pos);
  66. result = 0;
  67. switch ((unsigned int) filp->f_pos) {
  68. case 0:
  69. if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
  70. goto out;
  71. filp->f_pos = 1;
  72. /* fallthrough */
  73. case 1:
  74. if (filldir(dirent, "..", 2, 1,
  75.     dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
  76. goto out;
  77. filp->f_pos = 2;
  78. }
  79. /*
  80.  * Make sure our inode is up-to-date.
  81.  */
  82. result = smb_revalidate_inode(dentry);
  83. if (result)
  84. goto out;
  85. page = grab_cache_page(&dir->i_data, 0);
  86. if (!page)
  87. goto read_really;
  88. ctl.cache = cache = kmap(page);
  89. ctl.head  = cache->head;
  90. if (!Page_Uptodate(page) || !ctl.head.eof) {
  91. VERBOSE("%s/%s, page uptodate=%d, eof=%dn",
  92.  DENTRY_PATH(dentry), Page_Uptodate(page),ctl.head.eof);
  93. goto init_cache;
  94. }
  95. if (filp->f_pos == 2) {
  96. if (jiffies - ctl.head.time >= SMB_MAX_AGE(server))
  97. goto init_cache;
  98. /*
  99.  * N.B. ncpfs checks mtime of dentry too here, we don't.
  100.  *   1. common smb servers do not update mtime on dir changes
  101.  *   2. it requires an extra smb request
  102.  *      (revalidate has the same timeout as ctl.head.time)
  103.  *
  104.  * Instead smbfs invalidates its own cache on local changes
  105.  * and remote changes are not seen until timeout.
  106.  */
  107. }
  108. if (filp->f_pos > ctl.head.end)
  109. goto finished;
  110. ctl.fpos = filp->f_pos + (SMB_DIRCACHE_START - 2);
  111. ctl.ofs  = ctl.fpos / SMB_DIRCACHE_SIZE;
  112. ctl.idx  = ctl.fpos % SMB_DIRCACHE_SIZE;
  113. for (;;) {
  114. if (ctl.ofs != 0) {
  115. ctl.page = find_lock_page(&dir->i_data, ctl.ofs);
  116. if (!ctl.page)
  117. goto invalid_cache;
  118. ctl.cache = kmap(ctl.page);
  119. if (!Page_Uptodate(ctl.page))
  120. goto invalid_cache;
  121. }
  122. while (ctl.idx < SMB_DIRCACHE_SIZE) {
  123. struct dentry *dent;
  124. int res;
  125. dent = smb_dget_fpos(ctl.cache->dentry[ctl.idx],
  126.      dentry, filp->f_pos);
  127. if (!dent)
  128. goto invalid_cache;
  129. res = filldir(dirent, dent->d_name.name,
  130.       dent->d_name.len, filp->f_pos,
  131.       dent->d_inode->i_ino, DT_UNKNOWN);
  132. dput(dent);
  133. if (res)
  134. goto finished;
  135. filp->f_pos += 1;
  136. ctl.idx += 1;
  137. if (filp->f_pos > ctl.head.end)
  138. goto finished;
  139. }
  140. if (ctl.page) {
  141. kunmap(ctl.page);
  142. SetPageUptodate(ctl.page);
  143. UnlockPage(ctl.page);
  144. page_cache_release(ctl.page);
  145. ctl.page = NULL;
  146. }
  147. ctl.idx  = 0;
  148. ctl.ofs += 1;
  149. }
  150. invalid_cache:
  151. if (ctl.page) {
  152. kunmap(ctl.page);
  153. UnlockPage(ctl.page);
  154. page_cache_release(ctl.page);
  155. ctl.page = NULL;
  156. }
  157. ctl.cache = cache;
  158. init_cache:
  159. smb_invalidate_dircache_entries(dentry);
  160. ctl.head.time = jiffies;
  161. ctl.head.eof = 0;
  162. ctl.fpos = 2;
  163. ctl.ofs = 0;
  164. ctl.idx = SMB_DIRCACHE_START;
  165. ctl.filled = 0;
  166. ctl.valid  = 1;
  167. read_really:
  168. result = smb_proc_readdir(filp, dirent, filldir, &ctl);
  169. if (ctl.idx == -1)
  170. goto invalid_cache; /* retry */
  171. ctl.head.end = ctl.fpos - 1;
  172. ctl.head.eof = ctl.valid;
  173. finished:
  174. if (page) {
  175. cache->head = ctl.head;
  176. kunmap(page);
  177. SetPageUptodate(page);
  178. UnlockPage(page);
  179. page_cache_release(page);
  180. }
  181. if (ctl.page) {
  182. kunmap(ctl.page);
  183. SetPageUptodate(ctl.page);
  184. UnlockPage(ctl.page);
  185. page_cache_release(ctl.page);
  186. }
  187. out:
  188. return result;
  189. }
  190. static int
  191. smb_dir_open(struct inode *dir, struct file *file)
  192. {
  193. struct dentry *dentry = file->f_dentry;
  194. struct smb_sb_info *server;
  195. int error = 0;
  196. VERBOSE("(%s/%s)n", dentry->d_parent->d_name.name,
  197. file->f_dentry->d_name.name);
  198. /*
  199.  * Directory timestamps in the core protocol aren't updated
  200.  * when a file is added, so we give them a very short TTL.
  201.  */
  202. lock_kernel();
  203. server = server_from_dentry(dentry);
  204. if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
  205. unsigned long age = jiffies - dir->u.smbfs_i.oldmtime;
  206. if (age > 2*HZ)
  207. smb_invalid_dir_cache(dir);
  208. }
  209. /*
  210.  * Note: in order to allow the smbmount process to open the
  211.  * mount point, we only revalidate if the connection is valid or
  212.  * if the process is trying to access something other than the root.
  213.  */
  214. if (server->state == CONN_VALID || !IS_ROOT(dentry))
  215. error = smb_revalidate_inode(dentry);
  216. unlock_kernel();
  217. return error;
  218. }
  219. /*
  220.  * Dentry operations routines
  221.  */
  222. static int smb_lookup_validate(struct dentry *, int);
  223. static int smb_hash_dentry(struct dentry *, struct qstr *);
  224. static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
  225. static int smb_delete_dentry(struct dentry *);
  226. static struct dentry_operations smbfs_dentry_operations =
  227. {
  228. d_revalidate: smb_lookup_validate,
  229. d_hash: smb_hash_dentry,
  230. d_compare: smb_compare_dentry,
  231. d_delete: smb_delete_dentry,
  232. };
  233. static struct dentry_operations smbfs_dentry_operations_case =
  234. {
  235. d_revalidate: smb_lookup_validate,
  236. d_delete: smb_delete_dentry,
  237. };
  238. /*
  239.  * This is the callback when the dcache has a lookup hit.
  240.  */
  241. static int
  242. smb_lookup_validate(struct dentry * dentry, int flags)
  243. {
  244. struct smb_sb_info *server = server_from_dentry(dentry);
  245. struct inode * inode = dentry->d_inode;
  246. unsigned long age = jiffies - dentry->d_time;
  247. int valid;
  248. /*
  249.  * The default validation is based on dentry age:
  250.  * we believe in dentries for a few seconds.  (But each
  251.  * successful server lookup renews the timestamp.)
  252.  */
  253. valid = (age <= SMB_MAX_AGE(server));
  254. #ifdef SMBFS_DEBUG_VERBOSE
  255. if (!valid)
  256. VERBOSE("%s/%s not valid, age=%lun", 
  257. DENTRY_PATH(dentry), age);
  258. #endif
  259. if (inode) {
  260. lock_kernel();
  261. if (is_bad_inode(inode)) {
  262. PARANOIA("%s/%s has dud inoden", DENTRY_PATH(dentry));
  263. valid = 0;
  264. } else if (!valid)
  265. valid = (smb_revalidate_inode(dentry) == 0);
  266. unlock_kernel();
  267. } else {
  268. /*
  269.  * What should we do for negative dentries?
  270.  */
  271. }
  272. return valid;
  273. }
  274. static int 
  275. smb_hash_dentry(struct dentry *dir, struct qstr *this)
  276. {
  277. unsigned long hash;
  278. int i;
  279. hash = init_name_hash();
  280. for (i=0; i < this->len ; i++)
  281. hash = partial_name_hash(tolower(this->name[i]), hash);
  282. this->hash = end_name_hash(hash);
  283.   
  284. return 0;
  285. }
  286. static int
  287. smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b)
  288. {
  289. int i, result = 1;
  290. if (a->len != b->len)
  291. goto out;
  292. for (i=0; i < a->len; i++) {
  293. if (tolower(a->name[i]) != tolower(b->name[i]))
  294. goto out;
  295. }
  296. result = 0;
  297. out:
  298. return result;
  299. }
  300. /*
  301.  * This is the callback from dput() when d_count is going to 0.
  302.  * We use this to unhash dentries with bad inodes.
  303.  */
  304. static int
  305. smb_delete_dentry(struct dentry * dentry)
  306. {
  307. if (dentry->d_inode) {
  308. if (is_bad_inode(dentry->d_inode)) {
  309. PARANOIA("bad inode, unhashing %s/%sn",
  310.  DENTRY_PATH(dentry));
  311. return 1;
  312. }
  313. } else {
  314. /* N.B. Unhash negative dentries? */
  315. }
  316. return 0;
  317. }
  318. /*
  319.  * Initialize a new dentry
  320.  */
  321. void
  322. smb_new_dentry(struct dentry *dentry)
  323. {
  324. struct smb_sb_info *server = server_from_dentry(dentry);
  325. if (server->mnt->flags & SMB_MOUNT_CASE)
  326. dentry->d_op = &smbfs_dentry_operations_case;
  327. else
  328. dentry->d_op = &smbfs_dentry_operations;
  329. dentry->d_time = jiffies;
  330. }
  331. /*
  332.  * Whenever a lookup succeeds, we know the parent directories
  333.  * are all valid, so we want to update the dentry timestamps.
  334.  * N.B. Move this to dcache?
  335.  */
  336. void
  337. smb_renew_times(struct dentry * dentry)
  338. {
  339. for (;;) {
  340. dentry->d_time = jiffies;
  341. if (IS_ROOT(dentry))
  342. break;
  343. dentry = dentry->d_parent;
  344. }
  345. }
  346. static struct dentry *
  347. smb_lookup(struct inode *dir, struct dentry *dentry)
  348. {
  349. struct smb_fattr finfo;
  350. struct inode *inode;
  351. int error;
  352. struct smb_sb_info *server;
  353. error = -ENAMETOOLONG;
  354. if (dentry->d_name.len > SMB_MAXNAMELEN)
  355. goto out;
  356. error = smb_proc_getattr(dentry, &finfo);
  357. #ifdef SMBFS_PARANOIA
  358. if (error && error != -ENOENT)
  359. PARANOIA("find %s/%s failed, error=%dn",
  360.  DENTRY_PATH(dentry), error);
  361. #endif
  362. inode = NULL;
  363. if (error == -ENOENT)
  364. goto add_entry;
  365. if (!error) {
  366. error = -EACCES;
  367. finfo.f_ino = iunique(dentry->d_sb, 2);
  368. inode = smb_iget(dir->i_sb, &finfo);
  369. if (inode) {
  370. add_entry:
  371. server = server_from_dentry(dentry);
  372. if (server->mnt->flags & SMB_MOUNT_CASE)
  373. dentry->d_op = &smbfs_dentry_operations_case;
  374. else
  375. dentry->d_op = &smbfs_dentry_operations;
  376. d_add(dentry, inode);
  377. smb_renew_times(dentry);
  378. error = 0;
  379. }
  380. }
  381. out:
  382. return ERR_PTR(error);
  383. }
  384. /*
  385.  * This code is common to all routines creating a new inode.
  386.  */
  387. static int
  388. smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
  389. {
  390. struct smb_sb_info *server = server_from_dentry(dentry);
  391. struct inode *inode;
  392. int error;
  393. struct smb_fattr fattr;
  394. VERBOSE("file %s/%s, fileid=%un", DENTRY_PATH(dentry), fileid);
  395. error = smb_proc_getattr(dentry, &fattr);
  396. if (error)
  397. goto out_close;
  398. smb_renew_times(dentry);
  399. fattr.f_ino = iunique(dentry->d_sb, 2);
  400. inode = smb_iget(dentry->d_sb, &fattr);
  401. if (!inode)
  402. goto out_no_inode;
  403. if (have_id) {
  404. inode->u.smbfs_i.fileid = fileid;
  405. inode->u.smbfs_i.access = SMB_O_RDWR;
  406. inode->u.smbfs_i.open = server->generation;
  407. }
  408. d_instantiate(dentry, inode);
  409. out:
  410. return error;
  411. out_no_inode:
  412. error = -EACCES;
  413. out_close:
  414. if (have_id) {
  415. PARANOIA("%s/%s failed, error=%d, closing %un",
  416.  DENTRY_PATH(dentry), error, fileid);
  417. smb_close_fileid(dentry, fileid);
  418. }
  419. goto out;
  420. }
  421. /* N.B. How should the mode argument be used? */
  422. static int
  423. smb_create(struct inode *dir, struct dentry *dentry, int mode)
  424. {
  425. __u16 fileid;
  426. int error;
  427. VERBOSE("creating %s/%s, mode=%dn", DENTRY_PATH(dentry), mode);
  428. smb_invalid_dir_cache(dir);
  429. error = smb_proc_create(dentry, 0, CURRENT_TIME, &fileid);
  430. if (!error) {
  431. error = smb_instantiate(dentry, fileid, 1);
  432. } else {
  433. PARANOIA("%s/%s failed, error=%dn",
  434.  DENTRY_PATH(dentry), error);
  435. }
  436. return error;
  437. }
  438. /* N.B. How should the mode argument be used? */
  439. static int
  440. smb_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  441. {
  442. int error;
  443. smb_invalid_dir_cache(dir);
  444. error = smb_proc_mkdir(dentry);
  445. if (!error) {
  446. error = smb_instantiate(dentry, 0, 0);
  447. }
  448. return error;
  449. }
  450. static int
  451. smb_rmdir(struct inode *dir, struct dentry *dentry)
  452. {
  453. struct inode *inode = dentry->d_inode;
  454. int error;
  455. /*
  456.  * Close the directory if it's open.
  457.  */
  458. smb_close(inode);
  459. /*
  460.  * Check that nobody else is using the directory..
  461.  */
  462. error = -EBUSY;
  463. if (!d_unhashed(dentry))
  464. goto out;
  465. smb_invalid_dir_cache(dir);
  466. error = smb_proc_rmdir(dentry);
  467. out:
  468. return error;
  469. }
  470. static int
  471. smb_unlink(struct inode *dir, struct dentry *dentry)
  472. {
  473. int error;
  474. /*
  475.  * Close the file if it's open.
  476.  */
  477. smb_close(dentry->d_inode);
  478. smb_invalid_dir_cache(dir);
  479. error = smb_proc_unlink(dentry);
  480. if (!error)
  481. smb_renew_times(dentry);
  482. return error;
  483. }
  484. static int
  485. smb_rename(struct inode *old_dir, struct dentry *old_dentry,
  486.    struct inode *new_dir, struct dentry *new_dentry)
  487. {
  488. int error;
  489. /*
  490.  * Close any open files, and check whether to delete the
  491.  * target before attempting the rename.
  492.  */
  493. if (old_dentry->d_inode)
  494. smb_close(old_dentry->d_inode);
  495. if (new_dentry->d_inode) {
  496. smb_close(new_dentry->d_inode);
  497. error = smb_proc_unlink(new_dentry);
  498. if (error) {
  499. VERBOSE("unlink %s/%s, error=%dn",
  500. DENTRY_PATH(new_dentry), error);
  501. goto out;
  502. }
  503. /* FIXME */
  504. d_delete(new_dentry);
  505. }
  506. smb_invalid_dir_cache(old_dir);
  507. smb_invalid_dir_cache(new_dir);
  508. error = smb_proc_mv(old_dentry, new_dentry);
  509. if (!error) {
  510. smb_renew_times(old_dentry);
  511. smb_renew_times(new_dentry);
  512. }
  513. out:
  514. return error;
  515. }