���� 12-2  linux/fs/bitmap.c


  1 /*

  2  *  linux/fs/bitmap.c

  3  *

  4  *  (C) 1991  Linus Torvalds

  5  */

  6

  7 /* bitmap.c contains the code that handles the inode and block bitmaps */

    /* bitmap.c�����д���i�ڵ�ʹ��̿�λͼ�Ĵ��� */

  8 #include <string.h>       // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����

  9                           // ����ʹ�������е�memset()������

 10 #include <linux/sched.h>  // ���ȳ���ͷ�ļ�����������ṹtask_struct������0���ݡ�

 11 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣

 12

    //// ��ָ����ַ��addr������һ��1024�ֽ��ڴ����㡣

    // ���룺eax = 0��ecx = �Գ���Ϊ��λ�����ݿ鳤�ȣ�BLOCK_SIZE/4����edi = ָ����ʼ��

    // ַaddr��

 13 #define clear_block(addr) \

 14 __asm__("cld\n\t" \                // �巽��λ��

 15         "rep\n\t" \                // �ظ�ִ�д洢���ݣ�0����

 16         "stosl" \

 17         ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")

 18

    //// ��ָ����ַ��ʼ�ĵ�nr��λƫ�ƴ��ı���λ��λ��nr�ɴ���32����������ԭ����λֵ��

    // ���룺%0 -eax������ֵ����%1 -eax(0)��%2 -nr��λƫ��ֵ��%3 -(addr)��addr�����ݡ�

    // ��20�ж�����һ���ֲ��Ĵ�������res���ñ�������������ָ����eax�Ĵ����У��Ա���

    // ��Ч���ʺͲ��������ֶ�������ķ�����Ҫ������Ƕ�������С���ϸ˵���μ�gcc�ֲ�

    // ����ָ���Ĵ����еı������������궨����һ��������ʽ���ñ���ʽֵ�����res��ֵ��

    // ��21���ϵ�btslָ�����ڲ��Բ����ñ���λ��Bit Test and Set�����ѻ���ַ��%3����

    // ����λƫ��ֵ��%2����ָ���ı���λֵ�ȱ��浽��λ��־CF�У�Ȼ�����øñ���λΪ1��

    // ָ��setb���ڸ��ݽ�λ��־CF���ò�������%al�������CF=1��%al =1������%al =0��

 19 #define set_bit(nr,addr) ({\

 20 register int res __asm__("ax"); \

 21 __asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \

 22 "=a" (res):"" (0),"r" (nr),"m" (*(addr))); \

 23 res;})

 24

    //// ��λָ����ַ��ʼ�ĵ�nrλƫ�ƴ��ı���λ������ԭ����λֵ�ķ��롣

    // ���룺%0 -eax������ֵ����%1 -eax(0)��%2 -nr��λƫ��ֵ��%3 -(addr)��addr�����ݡ�

    // ��27���ϵ�btrlָ�����ڲ��Բ���λ����λ��Bit Test and Reset�����������������

    // btsl���ƣ����Ǹ�λָ������λ��ָ��setnb���ڸ��ݽ�λ��־CF���ò�������%al����

    // ���CF = 1��%al = 0������%al = 1��

 25 #define clear_bit(nr,addr) ({\

 26 register int res __asm__("ax"); \

 27 __asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \

 28 "=a" (res):"" (0),"r" (nr),"m" (*(addr))); \

 29 res;})

 30

    //// ��addr��ʼѰ�ҵ�1��0ֵ����λ��

    // ���룺%0 - ecx(����ֵ)��%1 - ecx(0)��%2 - esi(addr)��

    // ��addrָ����ַ��ʼ��λͼ��Ѱ�ҵ�1����0�ı���λ�����������addr�ı���λƫ��

    // ֵ���ء�addr�ǻ�����������ĵ�ַ��ɨ��Ѱ�ҵķ�Χ��1024�ֽڣ�8192����λ����

 31 #define find_first_zero(addr) ({ \

 32 int __res; \

 33 __asm__("cld\n" \                   // �巽��λ��

 34         "1:\tlodsl\n\t" \           // ȡ[esi]��eax��

 35         "notl %%eax\n\t" \          // eax��ÿλȡ����

 36         "bsfl %%eax,%%edx\n\t" \    // ��λ0ɨ��eax����1�ĵ�1��λ����ƫ��ֵ��edx��

 37         "je 2f\n\t" \               // ���eax��ȫ��0������ǰ��ת�����2��(40��)��

 38         "addl %%edx,%%ecx\n\t" \    // ƫ��ֵ����ecx��ecx��λͼ�׸�0ֵλ��ƫ��ֵ����

 39         "jmp 3f\n" \                // ��ǰ��ת�����3������������

 40         "2:\taddl $32,%%ecx\n\t" \  // δ�ҵ�0ֵλ����ecx��1�����ֵ�λƫ����32��

 41         "cmpl $8192,%%ecx\n\t" \    // �Ѿ�ɨ����8192����λ��1024�ֽڣ�����

 42         "jl 1b\n" \                 // ����û��ɨ����1�����ݣ�����ǰ��ת�����1����

 43         "3:" \                      // ��������ʱecx����λƫ������

 44         :"=c" (__res):"c" (0),"S" (addr):"ax","dx","si"); \

 45 __res;})

 46

    //// �ͷ��豸dev���������е��߼���block��

    // ��λָ���߼���block��Ӧ���߼���λͼ����λ���ɹ��򷵻�1�����򷵻�0��

    // ������dev���豸�ţ�block���߼���ţ��̿�ţ���

 47 int free_block(int dev, int block)

 48 {

 49         struct super_block * sb;

 50         struct buffer_head * bh;

 51

    // ����ȡ�豸dev���ļ�ϵͳ�ij�������Ϣ������������������ʼ�߼���ź��ļ�ϵͳ���߼�

    // ��������Ϣ�жϲ���block����Ч�ԡ����ָ���豸�����鲻���ڣ������ͣ�������߼���

    // ��С��������������1���߼���Ŀ�Ż��ߴ����豸�����߼�������Ҳ����ͣ����

 52         if (!(sb = get_super(dev)))                   // fs/super.c����56�С�

 53                 panic("trying to free block on nonexistent device");

 54         if (block < sb->s_firstdatazone || block >= sb->s_nzones)

 55                 panic("trying to free block not in datazone");

 56         bh = get_hash_table(dev,block);

    // Ȼ��� hash����Ѱ�Ҹÿ����ݡ����ҵ������ж�����Ч�ԣ��������޸ĺ͸��±�־���ͷ�

    // �����ݿ顣�öδ������Ҫ��;��������߼���Ŀǰ�����ڸ��ٻ������У����ͷŶ�Ӧ�Ļ�

    // ��顣

 57         if (bh) {

 58                 if (bh->b_count > 1) {     // ������ô�������1�������brelse()��

 59                         brelse(bh);        // b_count--���˳����ÿ黹�����á�

 60                         return 0;

 61                 }

 62                 bh->b_dirt=0;              // ����λ���޸ĺ��Ѹ��±�־��

 63                 bh->b_uptodate=0;

 64                 if (bh->b_count)           // ����ʱb_countΪ1�������brelse()�ͷ�֮��

 65                         brelse(bh);

 66         }

    // �������Ǹ�λblock���߼���λͼ�еı���λ����0�����ȼ���block����������ʼ�����

    // �����߼���ţ���1��ʼ��������Ȼ����߼���(����)λͼ���в�������λ��Ӧ�ı���λ��

    // �����Ӧ����λԭ������0�������ͣ��������1���������1024�ֽڣ���8192����λ��

    // ��� block/8192 ���ɼ����ָ���� block ���߼�λͼ�е��ĸ����ϡ��� block&8191 ��

    // �Եõ�block���߼���λͼ��ǰ���еı���ƫ��λ�á�

 67         block -= sb->s_firstdatazone - 1 ; // ��block = block - ( s_firstdatazone -1);

 68         if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) {

 69                 printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1);

 70                 printk("free_block: bit already cleared\n");

 71         }

    // �������Ӧ�߼���λͼ���ڻ��������޸ı�־��

 72         sb->s_zmap[block/8192]->b_dirt = 1;

 73         return 1;

 74 }

 75

    ////���豸����һ���߼��飨�̿飬���飩��

    // ��������ȡ���豸�ij����飬���ڳ������е��߼���λͼ��Ѱ�ҵ�һ��0ֵ����λ������

    // һ�������߼��飩��Ȼ����λ��Ӧ�߼������߼���λͼ�еı���λ������Ϊ���߼����ڻ�

    // ������ȡ��һ���Ӧ����顣��󽫸û�������㣬���������Ѹ��±�־�����޸ı�־��

    // �������߼���š�����ִ�гɹ��򷵻��߼���ţ��̿�ţ������򷵻�0��

 76 int new_block(int dev)

 77 {

 78         struct buffer_head * bh;

 79         struct super_block * sb;

 80         int i,j;

 81

    // ���Ȼ�ȡ�豸dev�ij����顣���ָ���豸�ij����鲻���ڣ������ͣ����Ȼ��ɨ���ļ�

    // ϵͳ��8���߼���λͼ��Ѱ���׸�0ֵ����λ����Ѱ�ҿ����߼��飬��ȡ���ø��߼����

    // ��š� ���ȫ��ɨ����8���߼���λͼ�����б���λ��i >= 8 �� j >= 8192����û�ҵ�

    // 0ֵ����λ����λͼ���ڵĻ����ָ����Ч(bh = NULL)�� ����0�˳���û�п����߼��飩��

 82         if (!(sb = get_super(dev)))

 83                 panic("trying to get new block from nonexistant device");

 84         j = 8192;

 85         for (i=0 ; i<8 ; i++)

 86                 if (bh=sb->s_zmap[i])

 87                         if ((j=find_first_zero(bh->b_data))<8192)

 88                                 break;

 89         if (i>=8 || !bh || j>=8192)

 90                 return 0;

    // ���������ҵ������߼���j��Ӧ�߼���λͼ�еı���λ������Ӧ����λ�Ѿ���λ�������

    // ͣ���������ô��λͼ�Ķ�Ӧ�����������޸ı�־����Ϊ�߼���λͼ����ʾ������������

    // �߼����ռ����������߼���λͼ�б���λƫ��ֵ��ʾ����������ʼ������Ŀ�ţ����

    // ������Ҫ������������1���߼���Ŀ�ţ���jת�����߼���š���ʱ������߼������

    // ���豸�ϵ����߼���������˵��ָ���߼����ڶ�Ӧ�豸�ϲ����ڡ�����ʧ�ܣ�����0�˳���

 91         if (set_bit(j,bh->b_data))

 92                 panic("new_block: bit already set");

 93         bh->b_dirt = 1;

 94         j += i*8192 + sb->s_firstdatazone-1;

 95         if (j >= sb->s_nzones)

 96                 return 0;

    // Ȼ���ڸ��ٻ�������Ϊ���豸��ָ�����߼����ȡ��һ������飬�����ػ����ͷָ�롣

    // ��Ϊ��ȡ�õ��߼��������ô���һ��Ϊ1��getblk()�л����ã����������Ϊ1��ͣ����

    // ������߼������㣬���������Ѹ��±�־�����޸ı�־��Ȼ���ͷŶ�Ӧ����飬����

    // �߼���š�

 97         if (!(bh=getblk(dev,j)))

 98                 panic("new_block: cannot get block");

 99         if (bh->b_count != 1)

100                 panic("new block: count is != 1");

101         clear_block(bh->b_data);

102         bh->b_uptodate = 1;

103         bh->b_dirt = 1;

104         brelse(bh);

105         return j;

106 }

107

    //// �ͷ�ָ����i�ڵ㡣

    // �ú��������жϲ���������i�ڵ�ŵ���Ч�ԺͿ��ͷ��ԡ���i�ڵ���Ȼ��ʹ��������

    // ���ͷš�Ȼ�����ó�������Ϣ��i�ڵ�λͼ���в�������λi�ڵ�Ŷ�Ӧ��i�ڵ�λͼ��

    // ����λ�������i�ڵ�ṹ��

108 void free_inode(struct m_inode * inode)

109 {

110         struct super_block * sb;

111         struct buffer_head * bh;

112

    // �����жϲ�����������Ҫ�ͷŵ�i�ڵ���Ч�Ի�Ϸ��ԡ����i�ڵ�ָ��=NULL�����˳���

    // ���i�ڵ��ϵ��豸���ֶ�Ϊ0��˵���ýڵ�û��ʹ�á�������0��ն�Ӧi�ڵ���ռ�ڴ�

    // �������ء�memset()������ include/string.h ��395�п�ʼ���������ʾ��0��дinode

    // ָ��ָ������������ sizeof(*inode) ���ڴ�顣

113         if (!inode)

114                 return;

115         if (!inode->i_dev) {

116                 memset(inode,0,sizeof(*inode));

117                 return;

118         }

    // �����i�ڵ㻹�������������ã������ͷţ�˵���ں������⣬ͣ��������ļ�������

    // ��Ϊ0�����ʾ���������ļ�Ŀ¼����ʹ�øýڵ㣬���Ҳ��Ӧ�ͷţ���Ӧ�÷Żصȡ�

119         if (inode->i_count>1) {

120                 printk("trying to free inode with count=%d\n",inode->i_count);

121                 panic("free_inode");

122         }

123         if (inode->i_nlinks)

124                 panic("trying to free inode with links");

    // ���ж���i�ڵ�ĺ�����֮�����ǿ�ʼ�����䳬������Ϣ�����е�i�ڵ�λͼ���в�����

    // ����ȡi�ڵ������豸�ij����飬�����豸�Ƿ���ڡ�Ȼ���ж�i�ڵ�ŵķ�Χ�Ƿ���ȷ��

    // ��� i�ڵ�ŵ���0 �� ���ڸ��豸�� i�ڵ��������������0��i�ڵ㱣��û��ʹ�ã���

    // �����i�ڵ��Ӧ�Ľڵ�λͼ�����ڣ����������Ϊһ��������i�ڵ�λͼ�� 8192 ��

    // ��λ�����i_num>>13����i_num/8192�����Եõ���ǰi�ڵ�����ڵ�s_imap[]�����

    // ���̿顣

125         if (!(sb = get_super(inode->i_dev)))

126                 panic("trying to free inode on nonexistent device");

127         if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)

128                 panic("trying to free inode 0 or nonexistant inode");

129         if (!(bh=sb->s_imap[inode->i_num>>13]))

130                 panic("nonexistent imap in superblock");

    // �������Ǹ�λi�ڵ��Ӧ�Ľڵ�λͼ�еı���λ������ñ���λ�Ѿ�����0������ʾ����

    // ������Ϣ�������i�ڵ�λͼ���ڻ��������޸ı�־������ո�i�ڵ�ṹ��ռ�ڴ�����

131         if (clear_bit(inode->i_num&8191,bh->b_data))

132                 printk("free_inode: bit already cleared.\n\r");

133         bh->b_dirt = 1;

134         memset(inode,0,sizeof(*inode));

135 }

136

    //// Ϊ�豸dev����һ����i�ڵ㡣��ʼ�������ظ���i�ڵ��ָ�롣

    // ���ڴ�i�ڵ���л�ȡһ������i�ڵ�������i�ڵ�λͼ����һ������i�ڵ㡣

137 struct m_inode * new_inode(int dev)

138 {

139         struct m_inode * inode;

140         struct super_block * sb;

141         struct buffer_head * bh;

142         int i,j;

143

    // ���ȴ��ڴ�i�ڵ����inode_table���л�ȡһ������i�ڵ������ȡָ���豸�ij�����

    // �ṹ�� Ȼ��ɨ�賬������8��i�ڵ�λͼ��Ѱ���׸�0����λ��Ѱ�ҿ��нڵ㣬��ȡ����

    // ��i�ڵ�Ľڵ�š����ȫ��ɨ���껹û�ҵ�������λͼ���ڵĻ������Ч��bh = NULL����

    // ��Ż���ǰ�����i�ڵ���е�i�ڵ㣬�����ؿ�ָ���˳���û�п���i�ڵ㣩��

144         if (!(inode=get_empty_inode()))             // fs/inode.c����197�С�

145                 return NULL;

146         if (!(sb = get_super(dev)))                 // fs/super.c����56�С�

147                 panic("new_inode with unknown device");

148         j = 8192;

149         for (i=0 ; i<8 ; i++)

150                 if (bh=sb->s_imap[i])

151                         if ((j=find_first_zero(bh->b_data))<8192)

152                                 break;

153         if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) {

154                 iput(inode);

155                 return NULL;

156         }

    // ���������Ѿ��ҵ��˻�δʹ�õ�i�ڵ��j��������λi�ڵ�j��Ӧ��i�ڵ�λͼ��Ӧ��

    // ��λ������Ѿ���λ�����������Ȼ����i�ڵ�λͼ���ڻ�������޸ı�־������ʼ��

    // ��i�ڵ�ṹ��i_ctime��i�ڵ����ݸı�ʱ�䣩��

157         if (set_bit(j,bh->b_data))

158                 panic("new_inode: bit already set");

159         bh->b_dirt = 1;

160         inode->i_count=1;                       // ���ü�����

161         inode->i_nlinks=1;                      // �ļ�Ŀ¼����������

162         inode->i_dev=dev;                       // i�ڵ����ڵ��豸�š�

163         inode->i_uid=current->euid;             // i�ڵ������û�id��

164         inode->i_gid=current->egid;             // ��id��

165         inode->i_dirt=1;                        // ���޸ı�־��λ��

166         inode->i_num = j + i*8192;              // ��Ӧ�豸�е�i�ڵ�š�

167         inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;  // ����ʱ�䡣

168         return inode;                           // ���ظ�i�ڵ�ָ�롣

169 }

170