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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/sysv/ialloc.c
  3.  *
  4.  *  minix/bitmap.c
  5.  *  Copyright (C) 1991, 1992  Linus Torvalds
  6.  *
  7.  *  ext/freelists.c
  8.  *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  9.  *
  10.  *  xenix/alloc.c
  11.  *  Copyright (C) 1992  Doug Evans
  12.  *
  13.  *  coh/alloc.c
  14.  *  Copyright (C) 1993  Pascal Haible, Bruno Haible
  15.  *
  16.  *  sysv/ialloc.c
  17.  *  Copyright (C) 1993  Bruno Haible
  18.  *
  19.  *  This file contains code for allocating/freeing inodes.
  20.  */
  21. #include <linux/kernel.h>
  22. #include <linux/fs.h>
  23. #include <linux/sysv_fs.h>
  24. #include <linux/stddef.h>
  25. #include <linux/stat.h>
  26. #include <linux/string.h>
  27. #include <linux/locks.h>
  28. /* We don't trust the value of
  29.    sb->sv_sbd2->s_tinode = *sb->sv_sb_total_free_inodes
  30.    but we nevertheless keep it up to date. */
  31. /* An inode on disk is considered free if both i_mode == 0 and i_nlink == 0. */
  32. /* return &sb->sv_sb_fic_inodes[i] = &sbd->s_inode[i]; */
  33. static inline sysv_ino_t *
  34. sv_sb_fic_inode(struct super_block * sb, unsigned int i)
  35. {
  36. if (sb->sv_bh1 == sb->sv_bh2)
  37. return &sb->sv_sb_fic_inodes[i];
  38. else {
  39. /* 512 byte Xenix FS */
  40. unsigned int offset = offsetof(struct xenix_super_block, s_inode[i]);
  41. if (offset < 512)
  42. return (sysv_ino_t*)(sb->sv_sbd1 + offset);
  43. else
  44. return (sysv_ino_t*)(sb->sv_sbd2 + offset);
  45. }
  46. }
  47. struct sysv_inode *
  48. sysv_raw_inode(struct super_block *sb, unsigned ino, struct buffer_head **bh)
  49. {
  50. struct sysv_inode *res;
  51. int block = sb->sv_firstinodezone + sb->sv_block_base;
  52. block += (ino-1) >> sb->sv_inodes_per_block_bits;
  53. *bh = sb_bread(sb, block);
  54. if (!*bh)
  55. return NULL;
  56. res = (struct sysv_inode *) (*bh)->b_data;
  57. return res + ((ino-1) & sb->sv_inodes_per_block_1);
  58. }
  59. static int refill_free_cache(struct super_block *sb)
  60. {
  61. struct buffer_head * bh;
  62. struct sysv_inode * raw_inode;
  63. int i = 0, ino;
  64. ino = SYSV_ROOT_INO+1;
  65. raw_inode = sysv_raw_inode(sb, ino, &bh);
  66. if (!raw_inode)
  67. goto out;
  68. while (ino <= sb->sv_ninodes) {
  69. if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) {
  70. *sv_sb_fic_inode(sb,i++) = cpu_to_fs16(sb, ino);
  71. if (i == sb->sv_fic_size)
  72. break;
  73. }
  74. if ((ino++ & sb->sv_inodes_per_block_1) == 0) {
  75. brelse(bh);
  76. raw_inode = sysv_raw_inode(sb, ino, &bh);
  77. if (!raw_inode)
  78. goto out;
  79. } else
  80. raw_inode++;
  81. }
  82. brelse(bh);
  83. out:
  84. return i;
  85. }
  86. void sysv_free_inode(struct inode * inode)
  87. {
  88. struct super_block * sb;
  89. unsigned int ino;
  90. struct buffer_head * bh;
  91. struct sysv_inode * raw_inode;
  92. unsigned count;
  93. sb = inode->i_sb;
  94. ino = inode->i_ino;
  95. if (ino <= SYSV_ROOT_INO || ino > sb->sv_ninodes) {
  96. printk("sysv_free_inode: inode 0,1,2 or nonexistent inoden");
  97. return;
  98. }
  99. raw_inode = sysv_raw_inode(sb, ino, &bh);
  100. clear_inode(inode);
  101. if (!raw_inode) {
  102. printk("sysv_free_inode: unable to read inode block on device "
  103.        "%sn", bdevname(inode->i_dev));
  104. return;
  105. }
  106. lock_super(sb);
  107. count = fs16_to_cpu(sb, *sb->sv_sb_fic_count);
  108. if (count < sb->sv_fic_size) {
  109. *sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sb, ino);
  110. *sb->sv_sb_fic_count = cpu_to_fs16(sb, count);
  111. }
  112. fs16_add(sb, sb->sv_sb_total_free_inodes, 1);
  113. dirty_sb(sb);
  114. memset(raw_inode, 0, sizeof(struct sysv_inode));
  115. mark_buffer_dirty(bh);
  116. unlock_super(sb);
  117. brelse(bh);
  118. }
  119. struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
  120. {
  121. struct inode * inode;
  122. struct super_block * sb;
  123. u16 ino;
  124. unsigned count;
  125. sb = dir->i_sb;
  126. inode = new_inode(sb);
  127. if (!inode)
  128. return ERR_PTR(-ENOMEM);
  129. lock_super(sb);
  130. count = fs16_to_cpu(sb, *sb->sv_sb_fic_count);
  131. if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) {
  132. count = refill_free_cache(sb);
  133. if (count == 0) {
  134. iput(inode);
  135. unlock_super(sb);
  136. return ERR_PTR(-ENOSPC);
  137. }
  138. }
  139. /* Now count > 0. */
  140. ino = *sv_sb_fic_inode(sb,--count);
  141. *sb->sv_sb_fic_count = cpu_to_fs16(sb, count);
  142. fs16_add(sb, sb->sv_sb_total_free_inodes, -1);
  143. dirty_sb(sb);
  144. if (dir->i_mode & S_ISGID) {
  145. inode->i_gid = dir->i_gid;
  146. if (S_ISDIR(mode))
  147. mode |= S_ISGID;
  148. } else
  149. inode->i_gid = current->fsgid;
  150. inode->i_uid = current->fsuid;
  151. inode->i_ino = fs16_to_cpu(sb, ino);
  152. inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  153. inode->i_blocks = inode->i_blksize = 0;
  154. inode->u.sysv_i.i_dir_start_lookup = 0;
  155. insert_inode_hash(inode);
  156. mark_inode_dirty(inode);
  157. inode->i_mode = mode; /* for sysv_write_inode() */
  158. sysv_write_inode(inode, 0); /* ensure inode not allocated again */
  159. mark_inode_dirty(inode); /* cleared by sysv_write_inode() */
  160. /* That's it. */
  161. unlock_super(sb);
  162. return inode;
  163. }
  164. unsigned long sysv_count_free_inodes(struct super_block * sb)
  165. {
  166. struct buffer_head * bh;
  167. struct sysv_inode * raw_inode;
  168. int ino, count, sb_count;
  169. lock_super(sb);
  170. sb_count = fs16_to_cpu(sb, *sb->sv_sb_total_free_inodes);
  171. if (0)
  172. goto trust_sb;
  173. /* this causes a lot of disk traffic ... */
  174. count = 0;
  175. ino = SYSV_ROOT_INO+1;
  176. raw_inode = sysv_raw_inode(sb, ino, &bh);
  177. if (!raw_inode)
  178. goto Eio;
  179. while (ino <= sb->sv_ninodes) {
  180. if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
  181. count++;
  182. if ((ino++ & sb->sv_inodes_per_block_1) == 0) {
  183. brelse(bh);
  184. raw_inode = sysv_raw_inode(sb, ino, &bh);
  185. if (!raw_inode)
  186. goto Eio;
  187. } else
  188. raw_inode++;
  189. }
  190. brelse(bh);
  191. if (count != sb_count)
  192. goto Einval;
  193. out:
  194. unlock_super(sb);
  195. return count;
  196. Einval:
  197. printk("sysv_count_free_inodes: "
  198. "free inode count was %d, correcting to %dn",
  199. sb_count, count);
  200. if (!(sb->s_flags & MS_RDONLY)) {
  201. *sb->sv_sb_total_free_inodes = cpu_to_fs16(sb, count);
  202. dirty_sb(sb);
  203. }
  204. goto out;
  205. Eio:
  206. printk("sysv_count_free_inodes: unable to read inode tablen");
  207. trust_sb:
  208. count = sb_count;
  209. goto out;
  210. }