����12-1 linux/fs/buffer.c


  1 /*

  2  *  linux/fs/buffer.c

  3  *

  4  *  (C) 1991  Linus Torvalds

  5  */

  6

  7 /*

  8  *  'buffer.c' implements the buffer-cache functions. Race-conditions have

  9  * been avoided by NEVER letting a interrupt change a buffer (except for the

 10  * data, of course), but instead letting the caller do it. NOTE! As interrupts

 11  * can wake up a caller, some cli-sti sequences are needed to check for

 12  * sleep-on-calls. These should be extremely quick, though (I hope).

 13  */

    /*

     * 'buffer.c'����ʵ�ֻ��������ٻ��湦�ܡ�ͨ�������жϴ������̸ı仺�����������õ�

     * ������ִ�У������˾�����������Ȼ���ı��������⣩��ע�⣡�����жϿ��Ի���һ����

     * ���ߣ���˾���Ҫ�����ж�ָ�cli-sti��������������ڵ��ö�˯�ߡ�����Ҫ�dz��ؿ�

     * ����ϣ������������

     */

 14

 15 /*

 16  * NOTE! There is one discordant note here: checking floppies for

 17  * disk change. This is where it fits best, I think, as it should

 18  * invalidate changed floppy-disk-caches.

 19  */

    /*

     * ע�⣡��һ������Ӧ�����������������Ƿ�����������������Ƿ���

     * �ó�����õĵط��ˣ���Ϊ����Ҫʹ�Ѹ������̻���ʧЧ��

     */

 20

 21 #include <stdarg.h>       // ��׼����ͷ�ļ����Ժ����ʽ������������б�����Ҫ˵����-��

                              // ����(va_list)��������(va_start, va_arg��va_end)������

                              // vsprintf��vprintf��vfprintf������

 22 

 23 #include <linux/config.h> // �ں�����ͷ�ļ�������������Ժ�Ӳ�����ͣ�HD_TYPE����ѡ�

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

                              // ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣

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

 26 #include <asm/system.h>   // ϵͳͷ�ļ������������û��޸�������/�ж��ŵȵ�Ƕ����ꡣ

 27 #include <asm/io.h>       // ioͷ�ļ�������Ӳ���˿�����/���������䡣

 28

    // ����end���ɱ���ʱ�����ӳ���ld���ɣ����ڱ����ں˴����ĩ�ˣ���ָ���ں�ģ��ĩ��

    // λ�ã��μ�����!δ�ҵ�����Դ����Ҳ���Դӱ����ں�ʱ���ɵ� System.map�ļ��в����������������

    // �����ٻ�������ʼ���ں˴���ĩ��λ�á�

    // ��33���ϵ�buffer_wait�����ǵȴ����л�����˯�ߵ��������ͷָ�롣���뻺���ͷ

    // ���ṹ��b_waitָ������ò�ͬ������������һ����������������ϵͳȱ�����ÿ��л�

    // ���ʱ����ǰ����ͻᱻ���ӵ�buffer_wait˯�ߵȴ������С���b_wait����ר�Ź��ȴ�

    // ָ������飨��b_wait��Ӧ�Ļ���飩������ʹ�õĵȴ�����ͷָ�롣

 29 extern int end;

 30 struct buffer_head * start_buffer = (struct buffer_head *) &end;

 31 struct buffer_head * hash_table[NR_HASH];        // NR_HASH = 307�

 32 static struct buffer_head * free_list;           // ���л��������ͷָ�롣

 33 static struct task_struct * buffer_wait = NULL;  // �ȴ����л�����˯�ߵ�������С�

 

    // ���涨��ϵͳ�������к��еĻ������������NR_BUFFERS��һ��������linux/fs.hͷ

    // �ļ���48�еĺ꣬��ֵ���DZ�����nr_buffers��������fs.h�ļ���172������Ϊȫ�ֱ�����

    // ��д����ͨ������һ�������ƣ�Linus������д������Ϊ�����������д�����������ر�ʾ

    // nr_buffers��һ�����ں˳�ʼ��֮���ٸı�ġ��������������ڳ�ʼ������buffer_init()

    // �б����ã���371�У���

 34 int NR_BUFFERS = 0;                              // ϵͳ���л���������

 35

    //// �ȴ�ָ������������

    // ���ָ���Ļ����bh�Ѿ��������ý��̲����жϵ�˯���ڸû����ĵȴ�����b_wait�С�

    // �ڻ�������ʱ����ȴ������ϵ����н��̽������ѡ���Ȼ���ڹر��жϣ�cli��֮��ȥ˯

    // �ߵģ���������������Ӱ����������������������Ӧ�жϡ���Ϊÿ�����̶����Լ���TSS��

    // �б����˱�־�Ĵ���EFLAGS��ֵ�������ڽ����л�ʱCPU�е�ǰEFLAGS��ֵҲ��֮�ı䡣

    // ʹ��sleep_on()����˯��״̬�Ľ�����Ҫ��wake_up()��ȷ�ػ��ѡ�

 36 static inline void wait_on_buffer(struct buffer_head * bh)

 37 {

 38         cli();                            // ���жϡ�

 39         while (bh->b_lock)                // ����ѱ���������̽���˯�ߣ��ȴ��������

 40                 sleep_on(&bh->b_wait);

 41         sti();                            // ���жϡ�

 42 }

 43

    //// �豸����ͬ����

    // ͬ���豸���ڴ���ٻ��������ݡ����У�sync_inodes()������inode.c��59�С�

 44 int sys_sync(void)

 45 {

 46         int i;

 47         struct buffer_head * bh;

 48

    // ���ȵ���i�ڵ�ͬ�����������ڴ�i�ڵ���������޸Ĺ���i�ڵ�д����ٻ����С�Ȼ��

    // ɨ�����и��ٻ����������ѱ��޸ĵĻ�������д�����󣬽�����������д�����У�����

    // ���ٻ����е��������豸�е�ͬ����

 49         sync_inodes();                           /* write out inodes into buffers */

 50         bh = start_buffer;                       // bhָ�򻺳�����ʼ����

 51         for (i=0 ; i<NR_BUFFERS ; i++,bh++) {

 52                 wait_on_buffer(bh);              // �ȴ�����������������������Ļ�����

 53                 if (bh->b_dirt)

 54                         ll_rw_block(WRITE,bh);   // ����д�豸������

 55         }

 56         return 0;

 57 }

 58

    //// ��ָ���豸���и��ٻ����������豸�����ݵ�ͬ��������

    // �ú��������������ٻ����������л���顣����ָ���豸dev�Ļ���飬���������ѱ��޸�

    // ����д�����У�ͬ����������Ȼ����ڴ���i�ڵ������д����ٻ����С�֮���ٶ�ָ����

    // ��devִ��һ����������ͬ��д�̲�����

 59 int sync_dev(int dev)

 60 {

 61         int i;

 62         struct buffer_head * bh;

 63

    // ���ȶԲ���ָ�����豸ִ������ͬ�����������豸�ϵ���������ٻ������е�����ͬ����

    // ������ɨ����ٻ����������л���飬��ָ���豸dev�Ļ���飬�ȼ�����Ƿ��ѱ�������

    // ���ѱ�������˯�ߵȴ��������Ȼ�����ж�һ�θû�����Ƿ���ָ���豸�Ļ���鲢��

    // ���޸Ĺ���b_dirt��־��λ�������ǾͶ���ִ��д�̲�������Ϊ������˯���ڼ�û����

    // �п����ѱ��ͷŻ��߱�Ų�����ã������ڼ���ִ��ǰ��Ҫ�ٴ��ж�һ�¸û�����Ƿ���

    // ָ���豸�Ļ���飬

 64         bh = start_buffer;                       // bhָ�򻺳�����ʼ����

 65         for (i=0 ; i<NR_BUFFERS ; i++,bh++) {   

 66                 if (bh->b_dev != dev)            // �����豸dev�Ļ�����������

 67                         continue;

 68                 wait_on_buffer(bh);              // �ȴ�����������������������Ļ�����

 69                 if (bh->b_dev == dev && bh->b_dirt)

 70                         ll_rw_block(WRITE,bh);

 71         }

    // �ٽ�i�ڵ�����д����ٻ��塣��i�ڵ��inode_table�е�inode�뻺���е���Ϣͬ����

 72         sync_inodes();

    // Ȼ���ڸ��ٻ����е����ݸ���֮���ٰ��������豸�е�����ͬ���������������ͬ������

    // ��Ϊ������ں�ִ��Ч�ʡ���һ�黺����ͬ�������������ں������ࡰ��顱��ɾ���ʹ��

    // i�ڵ��ͬ�������ܹ���Чִ�С����λ�����ͬ�����������Щ����i�ڵ�ͬ���������ֱ�

    // ��Ļ�������豸������ͬ����

 73         bh = start_buffer;

 74         for (i=0 ; i<NR_BUFFERS ; i++,bh++) {

 75                 if (bh->b_dev != dev)

 76                         continue;

 77                 wait_on_buffer(bh);

 78                 if (bh->b_dev == dev && bh->b_dirt)

 79                         ll_rw_block(WRITE,bh);

 80         }

 81         return 0;

 82 }

 83

    //// ʹָ���豸�ڸ��ٻ������е�������Ч��

    // ɨ����ٻ����������л���顣��ָ���豸�Ļ���鸴λ����Ч(����)��־�����޸ı�־��

 84 void inline invalidate_buffers(int dev)

 85 {

 86         int i;

 87         struct buffer_head * bh;

 88

 89         bh = start_buffer;

 90         for (i=0 ; i<NR_BUFFERS ; i++,bh++) {

 91                 if (bh->b_dev != dev)             // �������ָ���豸�Ļ���飬��

 92                         continue;                 // ����ɨ����һ�顣

 93                 wait_on_buffer(bh);               // �ȴ��û���������������ѱ���������

    // ���ڽ���ִ�й�˯�ߵȴ���������Ҫ���ж�һ�»������Ƿ���ָ���豸�ġ�

 94                 if (bh->b_dev == dev)

 95                         bh->b_uptodate = bh->b_dirt = 0;

 96         }

 97 }

 98

 99 /*

100  * This routine checks whether a floppy has been changed, and

101  * invalidates all buffer-cache-entries in that case. This

102  * is a relatively slow routine, so we have to try to minimize using

103  * it. Thus it is called only upon a 'mount' or 'open'. This

104  * is the best way of combining speed and utility, I think.

105  * People changing diskettes in the middle of an operation deserve

106  * to loose :-)

107  *

108  * NOTE! Although currently this is only for floppies, the idea is

109  * that any additional removable block-device will use this routine,

110  * and that mount/open needn't know that floppies/whatever are

111  * special.

112  */

    /*

     * ���ӳ�����һ�������Ƿ��ѱ�����������Ѿ�������ʹ���ٻ������������

     * ��Ӧ�����л�������Ч�����ӳ��������˵��������������Ҫ������ʹ������

     * ���Խ���ִ��'mount'��'open'ʱ�ŵ��������������ǽ��ٶȺ�ʵ�������ϵ�

     * ��÷��������ڲ��������и������̣��ͻᵼ�����ݵĶ�ʧ�����Ǿ�����ȡJ��

     *

     * ע�⣡����Ŀǰ���ӳ�����������̣��Ժ��κο��ƶ����ʵĿ��豸����ʹ�ø�

     * ����mount/open��������Ҫ֪�������̻�������ʲô������ʡ�

     */

    //// �������Ƿ����������Ѹ�����ʹ��Ӧ���ٻ�������Ч��

113 void check_disk_change(int dev)

114 {

115         int i;

116

    // ���ȼ��һ���Dz��������豸����Ϊ���ڽ�֧�����̿��ƶ����ʡ�����������˳���Ȼ��

    // ���������Ƿ��Ѹ��������û�����˳���floppy_change()��blk_drv/floppy.c��139�С�

117         if (MAJOR(dev) != 2)

118                 return;

119         if (!floppy_change(dev & 0x03))

120                 return;

    // �����Ѿ������������ͷŶ�Ӧ�豸��i�ڵ�λͼ���߼���λͼ��ռ�ĸ��ٻ���������ʹ��

    // �豸��i�ڵ�����ݿ���Ϣ��ռ��ĸ��ٻ������Ч��

121         for (i=0 ; i<NR_SUPER ; i++)

122                 if (super_block[i].s_dev == dev)

123                         put_super(super_block[i].s_dev);

124         invalidate_inodes(dev);

125         invalidate_buffers(dev);

126 }

127

    // �������д�����hash��ɢ�У����������hash����ļ���ꡣ

    // hash������Ҫ�����Ǽ��ٲ��ұȽ�Ԫ�������ѵ�ʱ�䡣ͨ����Ԫ�صĴ洢λ����ؼ���֮��

    // ����һ����Ӧ��ϵ��hash�����������ǾͿ���ֱ��ͨ�������������̲�ѯ��ָ����Ԫ�ء���

    // ��hash������ָ��������Ҫ�Ǿ���ȷ��ɢ�е��κ�������ĸ��ʻ�����ȡ����������ķ���

    // �ж��֣�����Linux 0.12��Ҫ�����˹ؼ��ֳ�������������Ϊ����Ѱ�ҵĻ����������������

    // ���豸��dev�ͻ�����block�������Ƶ�hash�����϶���Ҫ�����������ؼ�ֵ����������

    // �ؼ��ֵ�������ֻ�Ǽ���ؼ�ֵ��һ�ַ������ٶԹؼ�ֵ����MOD����Ϳ��Ա�֤��������

    // ��õ���ֵ�����ں��������Χ�ڡ�

128 #define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)

129 #define hash(dev,block) hash_table[_hashfn(dev,block)]

130

    //// ��hash���кͿ��л�����������߻���顣

    // hash������˫�������ṹ�����л���������˫��ѭ�������ṹ��

131 static inline void remove_from_queues(struct buffer_head * bh)

132 {

133 /* remove from hash-queue */

    /* ��hash�������Ƴ������ */

134         if (bh->b_next)

135                 bh->b_next->b_prev = bh->b_prev;

136         if (bh->b_prev)

137                 bh->b_prev->b_next = bh->b_next;

    // ����û������Ǹö��е�ͷһ���飬����hash���Ķ�Ӧ��ָ�򱾶����е���һ����������

138         if (hash(bh->b_dev,bh->b_blocknr) == bh)

139                 hash(bh->b_dev,bh->b_blocknr) = bh->b_next;

140 /* remove from free list */

    /* �ӿ��л��������Ƴ������ */

141         if (!(bh->b_prev_free) || !(bh->b_next_free))

142                 panic("Free block list corrupted");

143         bh->b_prev_free->b_next_free = bh->b_next_free;

144         bh->b_next_free->b_prev_free = bh->b_prev_free;

    // �����������ͷָ�򱾻�������������ָ����һ��������

145         if (free_list == bh)

146                 free_list = bh->b_next_free;

147 }

148

    //// �����������������β����ͬʱ����hash�����С�

149 static inline void insert_into_queues(struct buffer_head * bh)

150 {

151 /* put at end of free list */

    /* ���ڿ�������ĩβ�� */

152         bh->b_next_free = free_list;

153         bh->b_prev_free = free_list->b_prev_free;

154         free_list->b_prev_free->b_next_free = bh;

155         free_list->b_prev_free = bh;

156 /* put the buffer in new hash-queue if it has a device */

    /* ����û�����Ӧһ���豸�����������hash������ */

    // ��ע�⵱hash��ij���1�β�����ʱ��hash()����ֵ�϶�ΪNULL����˴�ʱ��161����

    // �õ���bh->b_next�϶���NULL�����Ե�163����Ӧ����bh->b_next��ΪNULLʱ���ܸ�

    // b_prev��bhֵ������163��ǰӦ�������жϡ�if (bh->b_next)�����ô���0.96���

    // �ű�������

157         bh->b_prev = NULL;

158         bh->b_next = NULL;

159         if (!bh->b_dev)

160                 return;

161         bh->b_next = hash(bh->b_dev,bh->b_blocknr);

162         hash(bh->b_dev,bh->b_blocknr) = bh;

163         bh->b_next->b_prev = bh;          // �˾�ǰӦ���ӡ�if (bh->b_next)���жϡ�

164 }

165

    //// ����hash���ڸ��ٻ�����Ѱ�Ҹ����豸��ָ����ŵĻ������顣

    // ����ҵ��򷵻ػ��������ָ�룬���򷵻�NULL��

166 static struct buffer_head * find_buffer(int dev, int block)

167 {              

168         struct buffer_head * tmp;

169

    // ����hash����Ѱ��ָ���豸�źͿ�ŵĻ���顣

170         for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)

171                 if (tmp->b_dev==dev && tmp->b_blocknr==block)

172                         return tmp;

173         return NULL;

174 }

175

176 /*

177  * Why like this, I hear you say... The reason is race-conditions.

178  * As we don't lock buffers (unless we are readint them, that is),

179  * something might happen to it while we sleep (ie a read-error

180  * will force it bad). This shouldn't really happen currently, but

181  * the code is ready.

182  */

    /*

     * ����Ϊʲô���������ӵģ�����������... ԭ���Ǿ�����������������û�ж�

     * ����������������������ڶ�ȡ�����е����ݣ�����ô�����ǣ����̣�˯��ʱ

     * �������ܻᷢ��һЩ���⣨����һ�������󽫵��¸û�����������Ŀǰ

     * �������ʵ�����Dz��ᷢ���ģ��������Ĵ����Ѿ�׼�����ˡ�

     */

    //// ����hash���ڸ��ٻ�������Ѱ��ָ���Ļ���顣���ҵ���Ըû�������������ؿ�ͷָ�롣

183 struct buffer_head * get_hash_table(int dev, int block)

184 {

185         struct buffer_head * bh;

186

187         for (;;) {

    // �ڸ��ٻ�����Ѱ�Ҹ����豸��ָ����Ļ������飬���û���ҵ��򷵻�NULL���˳���

188                 if (!(bh=find_buffer(dev,block)))

189                         return NULL;

    // �Ըû�����������ü��������ȴ��û�������������ѱ������������ھ�����˯��״̬��

    // ����б�Ҫ����֤�û�������ȷ�ԣ������ػ����ͷָ�롣

190                 bh->b_count++;

191                 wait_on_buffer(bh);

192                 if (bh->b_dev == dev && bh->b_blocknr == block)

193                         return bh;

    // �����˯��ʱ�û�����������豸�Ż��ŷ����˸ı䣬�������������ü���������Ѱ�ҡ�

194                 bh->b_count--;

195         }

196 }

197

198 /*

199  * Ok, this is getblk, and it isn't very clear, again to hinder

200  * race-conditions. Most of the code is seldom used, (ie repeating),

201  * so it should be much more efficient than it looks.

202  *

203  * The algoritm is changed: hopefully better, and an elusive bug removed.

204  */

    /*

     * OK��������getblk�������ú������߼������Ǻ�������ͬ��Ҳ����ΪҪ����

     * �����������⡣���д󲿷ִ�������õ���(�����ظ��������)�������Ӧ��

     * �ȿ���ȥ��������Ч�öࡣ

     *

     * �㷨�Ѿ����˸ı䣺ϣ���ܸ��ã�����һ��������ĥ�Ĵ����Ѿ�ȥ����

     */

    // ���������ͬʱ�жϻ��������޸ı�־��������־�����Ҷ����޸ı�־��Ȩ��Ҫ��������־

    // ��

205 #define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)

    //// ȡ���ٻ�����ָ���Ļ���顣

    // ���ָ�����豸�źͿ�ţ��Ļ������Ƿ��Ѿ��ڸ��ٻ����С����ָ�����Ѿ��ڸ��ٻ����У�

    // �򷵻ض�Ӧ������ͷָ���˳���������ڣ�����Ҫ�ڸ��ٻ���������һ����Ӧ�豸�źͿ�ŵ�

    // ���������Ӧ������ͷָ�롣

206 struct buffer_head * getblk(int dev,int block)

207 {

208         struct buffer_head * tmp, * bh;

209

210 repeat:

    // ����hash�������ָ�����Ѿ��ڸ��ٻ����У��򷵻ض�Ӧ������ͷָ�룬�˳���

211         if (bh = get_hash_table(dev,block))

212                 return bh;

    // ɨ��������ݿ�������Ѱ�ҿ��л�������

    // ������tmpָ����������ĵ�һ�����л�����ͷ��

213         tmp = free_list;

214         do {

    // ����û���������ʹ�ã����ü���������0���������ɨ����һ�����b_count=0�Ŀ飬

    // �����ٻ����е�ǰû�����õĿ鲻һ�����Ǹɾ��ģ�b_dirt=0����û�������ģ�b_lock=0����

    // ��ˣ����ǻ�����Ҫ����������жϺ�ѡ�����統һ�������д��һ�����ݺ���ͷ��ˣ�

    // ���Ǹÿ�b_count = 0����b_lock������0����һ������ִ�� breada()Ԥ��������ʱ��ֻҪ

    // ll_rw_block()����������ͻ�ݼ�b_count������ʱʵ����Ӳ�̷��ʲ������ܻ��ڽ��У�

    // ��˴�ʱb_lock=1����b_count=0��

215                 if (tmp->b_count)

216                         continue;

    // �������ͷָ��bhΪ�գ�����tmp��ָ����ͷ�ı�־(�޸ġ�����)Ȩ��С��bhͷ��־��Ȩ

    // �أ�����bhָ��tmp�����ͷ�� �����tmp�����ͷ����������û���޸�Ҳû��������

    // ־��λ����˵����Ϊָ���豸�ϵĿ�ȡ�ö�Ӧ�ĸ��ٻ���飬���˳�ѭ�����������Ǿͼ���

    // ִ�б�ѭ���������ܷ��ҵ�һ��BADNESS()��С�Ļ���졣

217                 if (!bh || BADNESS(tmp)<BADNESS(bh)) {

218                         bh = tmp;

219                         if (!BADNESS(tmp))

220                                 break;

221                 }

222 /* and repeat until we find something good */  /* �ظ�����ֱ���ҵ��ʺϵĻ���� */

223         } while ((tmp = tmp->b_next_free) != free_list);

    // ���ѭ����鷢�����л���鶼���ڱ�ʹ�ã����л�����ͷ�����ü�����>0���У���˯��

    // �ȴ��п��л������á����п��л�������ʱ�����̻ᱻ��ȷ�ػ��ѡ�Ȼ�����Ǿ���ת��

    // ������ʼ�����²��ҿ��л���顣

224         if (!bh) {

225                 sleep_on(&buffer_wait);

226                 goto repeat;                   // ��ת��210�С�

227         }

    // ִ�е����˵�������Ѿ��ҵ���һ���Ƚ��ʺϵĿ��л�����ˡ������ȵȴ��û���������

    //������ѱ������Ļ��������������˯�߽׶θû������ֱ���������ʹ�õĻ���ֻ���ظ�����

    // Ѱ�ҹ��̡�

228         wait_on_buffer(bh);

229         if (bh->b_count)                       // �ֱ�ռ�ã���

230                 goto repeat;

    // ����û������ѱ��޸ģ�������д�̣����ٴεȴ�������������ͬ���أ����û������ֱ�

    // ��������ʹ�õĻ���ֻ�����ظ�����Ѱ�ҹ��̡�

231         while (bh->b_dirt) {

232                 sync_dev(bh->b_dev);

233                 wait_on_buffer(bh);

234                 if (bh->b_count)               // �ֱ�ռ�ã���

235                         goto repeat;

236         }

237 /* NOTE!! While we slept waiting for this block, somebody else might */

238 /* already have added "this" block to the cache. check it */

    /* ע�⣡��������Ϊ�˵ȴ��û�����˯��ʱ���������̿����Ѿ����û���� */

     * ��������ٻ����У���������ҲҪ�Դ˽��м�顣*/

    // �ڸ��ٻ���hash���м��ָ���豸�Ϳ�Ļ�����Ƿ������˯��֮���Ѿ��������ȥ�����

    // �ǵĻ������ٴ��ظ�����Ѱ�ҹ��̡�

239         if (find_buffer(dev,block))

240                 goto repeat;

241 /* OK, FINALLY we know that this buffer is the only one of it's kind, */

242 /* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */

    /* OK����������֪���û������ָ��������Ψһһ�飬����Ŀǰ��û�б�ռ�� */

    /* (b_count=0)��Ҳδ������(b_lock=0)�������Ǹɾ��ģ�δ���޸ĵģ�*/

    // ����������ռ�ô˻���顣�����ü���Ϊ1����λ�޸ı�־����Ч(����)��־��

243         bh->b_count=1;

244         bh->b_dirt=0;

245         bh->b_uptodate=0;

    // ��hash���кͿ��п��������Ƴ��û�����ͷ���øû���������ָ���豸�����ϵ�ָ���顣

    // Ȼ����ݴ��µ��豸�źͿ�����²������������hash������λ�ô��������շ��ػ���

    // ͷָ�롣

246         remove_from_queues(bh);

247         bh->b_dev=dev;

248         bh->b_blocknr=block;

249         insert_into_queues(bh);

250         return bh;

251 }

252

    //// �ͷ�ָ������顣

    // �ȴ��û���������Ȼ�����ü����ݼ�1������ȷ�ػ��ѵȴ����л����Ľ��̡�

253 void brelse(struct buffer_head * buf)

254 {

255         if (!buf)                // �������ͷָ����Ч�򷵻ء�

256                 return;

257         wait_on_buffer(buf);

258         if (!(buf->b_count--))

259                 panic("Trying to free free buffer");

260         wake_up(&buffer_wait);

261 }

262

263 /*

264  * bread() reads a specified block and returns the buffer that contains

265  * it. It returns NULL if the block was unreadable.

266  */

    /*

     * ���豸�϶�ȡָ�������ݿ鲢���غ������ݵĻ����������ָ���Ŀ鲻����

     * �򷵻�NULL��

     */

    //// ���豸�϶�ȡ���ݿ顣

    // �ú�������ָ�����豸��dev�����ݿ��block�������ڸ��ٻ�����������һ�黺��顣

    // ����û�������Ѿ���������Ч�����ݾ�ֱ�ӷ��ظû����ָ�룬����ʹ��豸�ж�ȡ

    // ָ�������ݿ鵽�û�����в����ػ����ָ�롣

267 struct buffer_head * bread(int dev,int block)

268 {

269         struct buffer_head * bh;

270

    // �ڸ��ٻ�����������һ�黺��顣�������ֵ��NULL�����ʾ�ں˳�����ͣ����Ȼ������

    // �ж������Ƿ����п������ݡ� ����û��������������Ч�ģ��Ѹ��µģ�����ֱ��ʹ�ã�

    // �򷵻ء�

271         if (!(bh=getblk(dev,block)))

272                 panic("bread: getblk returned NULL\n");

273         if (bh->b_uptodate)

274                 return bh;

    // �������Ǿ͵��õײ���豸��дll_rw_block()�������������豸������Ȼ��ȴ�ָ��

    // ���ݿ鱻���룬���ȴ���������������˯������֮������û������Ѹ��£��򷵻ػ���

    // ��ͷָ�룬�˳�������������豸����ʧ�ܣ������ͷŸû�����������NULL���˳���

275         ll_rw_block(READ,bh);

276         wait_on_buffer(bh);

277         if (bh->b_uptodate)

278                 return bh;

279         brelse(bh);

280         return NULL;

281 }

282

    //// �����ڴ�顣

    // ��from��ַ����һ�飨1024�ֽڣ����ݵ�toλ�á�

283 #define COPYBLK(from,to) \

284 __asm__("cld\n\t" \

285         "rep\n\t" \

286         "movsl\n\t" \

287         ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \

288         :"cx","di","si")

289

290 /*

291  * bread_page reads four buffers into memory at the desired address. It's

292  * a function of its own, as there is some speed to be got by reading them

293  * all at the same time, not waiting for one to be read, and then another

294  * etc.

295  */

    /*

     * bread_pageһ�ζ��ĸ���������ݶ����ڴ�ָ���ĵ�ַ��������һ�������ĺ�����

     * ��Ϊͬʱ��ȡ�Ŀ���Ի���ٶ��ϵĺô������õ��Ŷ�һ�飬�ٶ�һ���ˡ�

     */

    //// ���豸��һ��ҳ�棨4������飩�����ݵ�ָ���ڴ��ַ����

    // ����address�DZ���ҳ�����ݵĵ�ַ��dev��ָ�����豸�ţ�b[4]�Ǻ���4���豸���ݿ��

    // �����顣�ú���������mm/memory.c�ļ���do_no_page()�����У���386�У���

296 void bread_page(unsigned long address,int dev,int b[4])

297 {

298         struct buffer_head * bh[4];

299         int i;

300

    // �ú���ѭ��ִ��4�Σ����ݷ�������b[]�е�4����Ŵ��豸dev�ж�ȡһҳ���ݷŵ�ָ��

    // �ڴ�λ�� address���� ���ڲ���b[i]��������Ч��ţ��������ȴӸ��ٻ�����ȡָ���豸

    // �Ϳ�ŵĻ���顣����������������Ч��δ���£���������豸������豸�϶�ȡ��Ӧ��

    // �ݿ顣����b[i]��Ч�Ŀ������ȥ�����ˡ���˱�������ʵ���Ը���ָ����b[]�еĿ��

    // �����ȡ1��4�����ݿ顣

301         for (i=0 ; i<4 ; i++)

302                 if (b[i]) {                      // �������Ч��

303                         if (bh[i] = getblk(dev,b[i]))

304                                 if (!bh[i]->b_uptodate)

305                                         ll_rw_block(READ,bh[i]);

306                 } else

307                         bh[i] = NULL;

    // ���4��������ϵ�����˳���Ƶ�ָ����ַ�����ڽ��и��ƣ�ʹ�ã������֮ǰ����

    // ��Ҫ˯�ߵȴ��������������������Ļ��������⣬��Ϊ����˯�߹��ˣ��������ǻ���Ҫ

    // �ڸ���֮ǰ�ټ��һ�»�����е������Ƿ�����Ч�ġ�����������ǻ���Ҫ�ͷŻ���顣

308         for (i=0 ; i<4 ; i++,address += BLOCK_SIZE)

309                 if (bh[i]) {

310                         wait_on_buffer(bh[i]);   // �ȴ���������(���������Ļ�)��

311                         if (bh[i]->b_uptodate)   // ���������������Ч�Ļ����ơ�

312                                 COPYBLK((unsigned long) bh[i]->b_data,address);

313                         brelse(bh[i]);           // �ͷŸû�������

314                 }

315 }

316

317 /*

318  * Ok, breada can be used as bread, but additionally to mark other

319  * blocks for reading as well. End the argument list with a negative

320  * number.

321  */

    /*

     * OK��breada������breadһ��ʹ�ã���������Ԥ��һЩ�顣�ú��������б�

     * ��Ҫʹ��һ�����������������б��Ľ�����

     */

    //// ��ָ���豸��ȡָ����һЩ�顣

    // �������������ɱ䣬��һϵ��ָ���Ŀ�š��ɹ�ʱ���ص�1��Ļ����ͷָ�룬���򷵻�

    // NULL��

322 struct buffer_head * breada(int dev,int first, ...)

323 {

324         va_list args;

325         struct buffer_head * bh, *tmp;

326

    // ����ȡ�ɱ�������е�1����������ţ������ŴӸ��ٻ�������ȡָ���豸�Ϳ�ŵĻ���

    // �顣����û����������Ч�����±�־δ��λ�����򷢳����豸���ݿ�����

327         va_start(args,first);

328         if (!(bh=getblk(dev,first)))

329                 panic("bread: getblk returned NULL\n");

330         if (!bh->b_uptodate)

331                 ll_rw_block(READ,bh);

    // Ȼ��˳��ȡ�ɱ������������Ԥ����ţ�����������ͬ���������������á�ע�⣬336����

    // ��һ��bug�����е�bhӦ����tmp�����bugֱ����0.96����ں˴����вű�����������

    // ���⣬��Ϊ������Ԥ���������ݿ飬ֻ��������ٻ��������������Ͼ�ʹ�ã����Ե�337

    // �������Ҫ�������ü����ݼ��ͷŵ��ÿ飨��Ϊgetblk()���������ӻ�������ü���ֵ����

332         while ((first=va_arg(args,int))>=0) {

333                 tmp=getblk(dev,first);

334                 if (tmp) {

335                         if (!tmp->b_uptodate)

336                                 ll_rw_block(READA,bh);    // bh Ӧ����tmp��

337                         tmp->b_count--;                   // ��ʱ�ͷŵ���Ԥ���顣

338                 }

339         }

    // ��ʱ�ɱ�����������в���������ϡ����ǵȴ���1������������������ѱ����������ڵ�

    // ���˳�֮�������������������Ȼ��Ч���򷵻ػ�����ͷָ���˳��������ͷŸû���������

    // NULL���˳���

340         va_end(args);

341         wait_on_buffer(bh);

342         if (bh->b_uptodate)

343                 return bh;

344         brelse(bh);

345         return (NULL);

346 }

347

    //// ��������ʼ��������

    // ����buffer_end�ǻ������ڴ�ĩ�ˡ����ھ���16MB�ڴ��ϵͳ��������ĩ�˱�����Ϊ4MB��

    // ������8MB�ڴ��ϵͳ��������ĩ�˱�����Ϊ2MB���ú����ӻ�������ʼλ��start_buffer

    // ���ͻ�����ĩ��buffer_end���ֱ�ͬʱ���ã���ʼ���������ͷ�ṹ�Ͷ�Ӧ�����ݿ顣ֱ��

    // �������������ڴ汻������ϡ��μ������б�ǰ���ʾ��ͼ��

348 void buffer_init(long buffer_end)

349 {

350         struct buffer_head * h = start_buffer;

351         void * b;

352         int i;

353

    // ���ȸ��ݲ����ṩ�Ļ������߶�λ��ȷ��ʵ�ʻ������߶�λ��b������������߶˵���1Mb��

    // ����Ϊ��640KB - 1MB����ʾ�ڴ�� BIOSռ�ã�����ʵ�ʿ��û������ڴ�߶�λ��Ӧ����

    // 640KB�����򻺳����ڴ�߶�һ������1MB��

354         if (buffer_end == 1<<20)

355                 b = (void *) (640*1024);

356         else

357                 b = (void *) buffer_end;

    // ��δ������ڳ�ʼ�����������������л����ѭ������������ȡϵͳ�л������Ŀ��������

    // �����Ǵӻ������߶˿�ʼ����1KB��С�Ļ���飬���ͬʱ�ڻ������Ͷ˽��������û����

    // �Ľṹbuffer_head��������Щbuffer_head���˫��������

    // h��ָ�򻺳�ͷ�ṹ��ָ�룬��h+1��ָ���ڴ��ַ��������һ������ͷ��ַ��Ҳ����˵��

    // ָ��h����ͷ��ĩ���⡣Ϊ�˱�֤���㹻���ȵ��ڴ����洢һ������ͷ�ṹ����Ҫb��ָ��

    // ���ڴ���ַ >= h����ͷ��ĩ�ˣ���Ҫ�� >= h+1��

358         while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) {

359                 h->b_dev = 0;               // ʹ�øû������豸�š�

360                 h->b_dirt = 0;              // ���־����������޸ı�־��

361                 h->b_count = 0;             // ��������ü�����

362                 h->b_lock = 0;              // �����������־��

363                 h->b_uptodate = 0;          // �������±�־�����������Ч��־����

364                 h->b_wait = NULL;           // ָ��ȴ��û��������Ľ��̡�

365                 h->b_next = NULL;           // ָ�������ͬhashֵ����һ������ͷ��

366                 h->b_prev = NULL;           // ָ�������ͬhashֵ��ǰһ������ͷ��

367                 h->b_data = (char *) b;     // ָ���Ӧ��������ݿ飨1024�ֽڣ���

368                 h->b_prev_free = h-1;       // ָ��������ǰһ�

369                 h->b_next_free = h+1;       // ָ����������һ�

370                 h++;                           // hָ����һ�»���ͷλ�á�

371                 NR_BUFFERS++;                  // �����������ۼӡ�

372                 if (b == (void *) 0x100000)    // ��b�ݼ�������1MB��������384KB��

373                         b = (void *) 0xA0000;  // ��bָ���ַ0xA0000(640KB)����

374         }

375         h--;                                // ��hָ�����һ����Ч�����ͷ��

376         free_list = start_buffer;           // �ÿ�������ͷָ��ͷһ������顣

377         free_list->b_prev_free = h;  // ����ͷ��b_prev_freeָ��ǰһ������һ���

378         h->b_next_free = free_list;         // h����һ��ָ��ָ���һ��γ�һ��������

    // ����ʼ��hash������ϣ����ɢ�б������ñ�������ָ��ΪNULL��

379         for (i=0;i<NR_HASH;i++)

380                 hash_table[i]=NULL;

381 }      

382