nfs.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /* fs/fat/nfs.c
  2. *
  3. * This software is licensed under the terms of the GNU General Public
  4. * License version 2, as published by the Free Software Foundation, and
  5. * may be copied, distributed, and modified under those terms.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/exportfs.h>
  14. #include "fat.h"
  15. /**
  16. * Look up a directory inode given its starting cluster.
  17. */
  18. static struct inode *fat_dget(struct super_block *sb, int i_logstart)
  19. {
  20. struct msdos_sb_info *sbi = MSDOS_SB(sb);
  21. struct hlist_head *head;
  22. struct hlist_node *_p;
  23. struct msdos_inode_info *i;
  24. struct inode *inode = NULL;
  25. head = sbi->dir_hashtable + fat_dir_hash(i_logstart);
  26. spin_lock(&sbi->dir_hash_lock);
  27. hlist_for_each_entry(i, _p, head, i_dir_hash) {
  28. BUG_ON(i->vfs_inode.i_sb != sb);
  29. if (i->i_logstart != i_logstart)
  30. continue;
  31. inode = igrab(&i->vfs_inode);
  32. if (inode)
  33. break;
  34. }
  35. spin_unlock(&sbi->dir_hash_lock);
  36. return inode;
  37. }
  38. static struct inode *fat_nfs_get_inode(struct super_block *sb,
  39. u64 ino, u32 generation)
  40. {
  41. struct inode *inode;
  42. if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO))
  43. return NULL;
  44. inode = ilookup(sb, ino);
  45. if (inode && generation && (inode->i_generation != generation)) {
  46. iput(inode);
  47. inode = NULL;
  48. }
  49. return inode;
  50. }
  51. /**
  52. * Map a NFS file handle to a corresponding dentry.
  53. * The dentry may or may not be connected to the filesystem root.
  54. */
  55. struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid,
  56. int fh_len, int fh_type)
  57. {
  58. return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
  59. fat_nfs_get_inode);
  60. }
  61. /*
  62. * Find the parent for a file specified by NFS handle.
  63. * This requires that the handle contain the i_ino of the parent.
  64. */
  65. struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid,
  66. int fh_len, int fh_type)
  67. {
  68. return generic_fh_to_parent(sb, fid, fh_len, fh_type,
  69. fat_nfs_get_inode);
  70. }
  71. /*
  72. * Find the parent for a directory that is not currently connected to
  73. * the filesystem root.
  74. *
  75. * On entry, the caller holds child_dir->d_inode->i_mutex.
  76. */
  77. struct dentry *fat_get_parent(struct dentry *child_dir)
  78. {
  79. struct super_block *sb = child_dir->d_sb;
  80. struct buffer_head *bh = NULL;
  81. struct msdos_dir_entry *de;
  82. struct inode *parent_inode = NULL;
  83. if (!fat_get_dotdot_entry(child_dir->d_inode, &bh, &de)) {
  84. int parent_logstart = fat_get_start(MSDOS_SB(sb), de);
  85. parent_inode = fat_dget(sb, parent_logstart);
  86. }
  87. brelse(bh);
  88. return d_obtain_alias(parent_inode);
  89. }