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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 2000-2001 Christoph Hellwig.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions, and the following disclaimer,
  10.  *    without modification.
  11.  * 2. The name of the author may not be used to endorse or promote products
  12.  *    derived from this software without specific prior written permission.
  13.  *
  14.  * Alternatively, this software may be distributed under the terms of the
  15.  * GNU General Public License ("GPL").
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20.  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21.  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27.  * SUCH DAMAGE.
  28.  */
  29. #ident "$Id: vxfs_inode.c,v 1.42 2002/01/02 23:51:36 hch Exp hch $"
  30. /*
  31.  * Veritas filesystem driver - inode routines.
  32.  */
  33. #include <linux/fs.h>
  34. #include <linux/pagemap.h>
  35. #include <linux/kernel.h>
  36. #include <linux/slab.h>
  37. #include "vxfs.h"
  38. #include "vxfs_inode.h"
  39. #include "vxfs_extern.h"
  40. extern struct address_space_operations vxfs_aops;
  41. extern struct address_space_operations vxfs_immed_aops;
  42. extern struct inode_operations vxfs_immed_symlink_iops;
  43. static struct file_operations vxfs_file_operations = {
  44. .open = generic_file_open,
  45. .llseek = generic_file_llseek,
  46. .read = generic_file_read,
  47. .mmap = generic_file_mmap,
  48. };
  49. kmem_cache_t *vxfs_inode_cachep;
  50. #ifdef DIAGNOSTIC
  51. /*
  52.  * Dump inode contents (partially).
  53.  */
  54. void
  55. vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
  56. {
  57. printk(KERN_DEBUG "nn");
  58. if (ino)
  59. printk(KERN_DEBUG "dumping vxfs inode %ldn", ino);
  60. else
  61. printk(KERN_DEBUG "dumping unknown vxfs inoden");
  62. printk(KERN_DEBUG "---------------------------n");
  63. printk(KERN_DEBUG "mode is %xn", vip->vii_mode);
  64. printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%un",
  65. vip->vii_nlink, vip->vii_uid, vip->vii_gid);
  66. printk(KERN_DEBUG "size:%Lx, blocks:%un",
  67. vip->vii_size, vip->vii_blocks);
  68. printk(KERN_DEBUG "orgtype:%un", vip->vii_orgtype);
  69. }
  70. #endif
  71. /**
  72.  * vxfs_blkiget - find inode based on extent #
  73.  * @sbp: superblock of the filesystem we search in
  74.  * @extent: number of the extent to search
  75.  * @ino: inode number to search
  76.  *
  77.  * Description:
  78.  *  vxfs_blkiget searches inode @ino in the filesystem described by
  79.  *  @sbp in the extent @extent.
  80.  *  Returns the matching VxFS inode on success, else a NULL pointer.
  81.  *
  82.  * NOTE:
  83.  *  While __vxfs_iget uses the pagecache vxfs_blkiget uses the
  84.  *  buffercache.  This function should not be used outside the
  85.  *  read_super() method, otherwise the data may be incoherent.
  86.  */
  87. struct vxfs_inode_info *
  88. vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
  89. {
  90. struct buffer_head *bp;
  91. u_long block, offset;
  92. block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize);
  93. offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
  94. bp = sb_bread(sbp, block);
  95. if (buffer_mapped(bp)) {
  96. struct vxfs_inode_info *vip;
  97. struct vxfs_dinode *dip;
  98. if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL)))
  99. goto fail;
  100. dip = (struct vxfs_dinode *)(bp->b_data + offset);
  101. memcpy(vip, dip, sizeof(*vip));
  102. #ifdef DIAGNOSTIC
  103. vxfs_dumpi(vip, ino);
  104. #endif
  105. brelse(bp);
  106. return (vip);
  107. }
  108. fail:
  109. printk(KERN_WARNING "vxfs: unable to read block %ldn", block);
  110. brelse(bp);
  111. return NULL;
  112. }
  113. /**
  114.  * __vxfs_iget - generic find inode facility
  115.  * @sbp: VFS superblock
  116.  * @ino: inode number
  117.  * @ilistp: inode list
  118.  *
  119.  * Description:
  120.  *  Search the for inode number @ino in the filesystem
  121.  *  described by @sbp.  Use the specified inode table (@ilistp).
  122.  *  Returns the matching VxFS inode on success, else a NULL pointer.
  123.  */
  124. static struct vxfs_inode_info *
  125. __vxfs_iget(ino_t ino, struct inode *ilistp)
  126. {
  127. struct page *pp;
  128. u_long offset;
  129. offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
  130. pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
  131. if (!IS_ERR(pp)) {
  132. struct vxfs_inode_info *vip;
  133. struct vxfs_dinode *dip;
  134. caddr_t kaddr = (char *)page_address(pp);
  135. if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL)))
  136. goto fail;
  137. dip = (struct vxfs_dinode *)(kaddr + offset);
  138. memcpy(vip, dip, sizeof(*vip));
  139. #ifdef DIAGNOSTIC
  140. vxfs_dumpi(vip, ino);
  141. #endif
  142. vxfs_put_page(pp);
  143. return (vip);
  144. }
  145. printk(KERN_WARNING "vxfs: error on page %pn", pp);
  146. return NULL;
  147. fail:
  148. printk(KERN_WARNING "vxfs: unable to read inode %ldn", ino);
  149. vxfs_put_page(pp);
  150. return NULL;
  151. }
  152. /**
  153.  * vxfs_stiget - find inode using the structural inode list
  154.  * @sbp: VFS superblock
  155.  * @ino: inode #
  156.  *
  157.  * Description:
  158.  *  Find inode @ino in the filesystem described by @sbp using
  159.  *  the structural inode list.
  160.  *  Returns the matching VxFS inode on success, else a NULL pointer.
  161.  */
  162. struct vxfs_inode_info *
  163. vxfs_stiget(struct super_block *sbp, ino_t ino)
  164. {
  165.         return __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
  166. }
  167. /**
  168.  * vxfs_transmod - mode for a VxFS inode
  169.  * @vip: VxFS inode
  170.  *
  171.  * Description:
  172.  *  vxfs_transmod returns a Linux mode_t for a given
  173.  *  VxFS inode structure.
  174.  */
  175. static __inline__ mode_t
  176. vxfs_transmod(struct vxfs_inode_info *vip)
  177. {
  178. mode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
  179. if (VXFS_ISFIFO(vip))
  180. ret |= S_IFIFO;
  181. if (VXFS_ISCHR(vip))
  182. ret |= S_IFCHR;
  183. if (VXFS_ISDIR(vip))
  184. ret |= S_IFDIR;
  185. if (VXFS_ISBLK(vip))
  186. ret |= S_IFBLK;
  187. if (VXFS_ISLNK(vip))
  188. ret |= S_IFLNK;
  189. if (VXFS_ISREG(vip))
  190. ret |= S_IFREG;
  191. if (VXFS_ISSOC(vip))
  192. ret |= S_IFSOCK;
  193. return (ret);
  194. }
  195. /**
  196.  * vxfs_iinit- helper to fill inode fields
  197.  * @ip: VFS inode
  198.  * @vip: VxFS inode
  199.  *
  200.  * Description:
  201.  *  vxfs_instino is a helper function to fill in all relevant
  202.  *  fields in @ip from @vip.
  203.  */
  204. static void
  205. vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
  206. {
  207. ip->i_mode = vxfs_transmod(vip);
  208. ip->i_uid = (uid_t)vip->vii_uid;
  209. ip->i_gid = (gid_t)vip->vii_gid;
  210. ip->i_nlink = vip->vii_nlink;
  211. ip->i_size = vip->vii_size;
  212. ip->i_atime = vip->vii_atime;
  213. ip->i_ctime = vip->vii_ctime;
  214. ip->i_mtime = vip->vii_mtime;
  215. ip->i_blksize = PAGE_SIZE;
  216. ip->i_blocks = vip->vii_blocks;
  217. ip->i_generation = vip->vii_gen;
  218. ip->u.generic_ip = (void *)vip;
  219. }
  220. /**
  221.  * vxfs_get_fake_inode - get fake inode structure
  222.  * @sbp: filesystem superblock
  223.  * @vip: fspriv inode
  224.  *
  225.  * Description:
  226.  *  vxfs_fake_inode gets a fake inode (not in the inode hash) for a
  227.  *  superblock, vxfs_inode pair.
  228.  *  Returns the filled VFS inode.
  229.  */
  230. struct inode *
  231. vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
  232. {
  233. struct inode *ip = NULL;
  234. if ((ip = new_inode(sbp))) {
  235. vxfs_iinit(ip, vip);
  236. ip->i_mapping->a_ops = &vxfs_aops;
  237. }
  238. return (ip);
  239. }
  240. /**
  241.  * vxfs_put_fake_inode - free faked inode
  242.  * *ip: VFS inode
  243.  *
  244.  * Description:
  245.  *  vxfs_put_fake_inode frees all data asssociated with @ip.
  246.  */
  247. void
  248. vxfs_put_fake_inode(struct inode *ip)
  249. {
  250. iput(ip);
  251. }
  252. /**
  253.  * vxfs_read_inode - fill in inode information
  254.  * @ip: inode pointer to fill
  255.  *
  256.  * Description:
  257.  *  vxfs_read_inode reads the disk inode for @ip and fills
  258.  *  in all relevant fields in @ip.
  259.  */
  260. void
  261. vxfs_read_inode(struct inode *ip)
  262. {
  263. struct super_block *sbp = ip->i_sb;
  264. struct vxfs_inode_info *vip;
  265. struct address_space_operations *aops;
  266. ino_t ino = ip->i_ino;
  267. if (!(vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist)))
  268. return;
  269. vxfs_iinit(ip, vip);
  270. if (VXFS_ISIMMED(vip))
  271. aops = &vxfs_immed_aops;
  272. else
  273. aops = &vxfs_aops;
  274. if (S_ISREG(ip->i_mode)) {
  275. ip->i_fop = &vxfs_file_operations;
  276. ip->i_mapping->a_ops = aops;
  277. } else if (S_ISDIR(ip->i_mode)) {
  278. ip->i_op = &vxfs_dir_inode_ops;
  279. ip->i_fop = &vxfs_dir_operations;
  280. ip->i_mapping->a_ops = aops;
  281. } else if (S_ISLNK(ip->i_mode)) {
  282. if (!VXFS_ISIMMED(vip)) {
  283. ip->i_op = &page_symlink_inode_operations;
  284. ip->i_mapping->a_ops = &vxfs_aops;
  285. } else
  286. ip->i_op = &vxfs_immed_symlink_iops;
  287. } else
  288. init_special_inode(ip, ip->i_mode, vip->vii_rdev);
  289. return;
  290. }
  291. /**
  292.  * vxfs_put_inode - remove inode from main memory
  293.  * @ip: inode to discard.
  294.  *
  295.  * Description:
  296.  *  vxfs_put_inode() is called on each iput.  If we are the last
  297.  *  link in memory, free the fspriv inode area.
  298.  */
  299. void
  300. vxfs_put_inode(struct inode *ip)
  301. {
  302. if (atomic_read(&ip->i_count) == 1)
  303. kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
  304. }