📄 buffer.c
字号:
<a name=L111 href="source/fs/buffer.c#L111">111</a> <b><i> * special.</i></b><a name=L112 href="source/fs/buffer.c#L112">112</a> <b><i> */</i></b><a name=L113 href="source/fs/buffer.c#L113">113</a> void <a href="ident?i=check_disk_change">check_disk_change</a>(int dev)<a name=L114 href="source/fs/buffer.c#L114">114</a> {<a name=L115 href="source/fs/buffer.c#L115">115</a> int i;<a name=L116 href="source/fs/buffer.c#L116">116</a> <a name=L117 href="source/fs/buffer.c#L117">117</a> if (<a href="ident?i=MAJOR">MAJOR</a>(dev) != 2)<a name=L118 href="source/fs/buffer.c#L118">118</a> return;<a name=L119 href="source/fs/buffer.c#L119">119</a> if (!<a href="ident?i=floppy_change">floppy_change</a>(dev & 0x03))<a name=L120 href="source/fs/buffer.c#L120">120</a> return;<a name=L121 href="source/fs/buffer.c#L121">121</a> for (i=0 ; i<<a href="ident?i=NR_SUPER">NR_SUPER</a> ; i++)<a name=L122 href="source/fs/buffer.c#L122">122</a> if (<a href="ident?i=super_block">super_block</a>[i].s_dev == dev)<a name=L123 href="source/fs/buffer.c#L123">123</a> <a href="ident?i=put_super">put_super</a>(<a href="ident?i=super_block">super_block</a>[i].s_dev);<a name=L124 href="source/fs/buffer.c#L124">124</a> <a href="ident?i=invalidate_inodes">invalidate_inodes</a>(dev);<a name=L125 href="source/fs/buffer.c#L125">125</a> <a href="ident?i=invalidate_buffers">invalidate_buffers</a>(dev);<a name=L126 href="source/fs/buffer.c#L126">126</a> }<a name=L127 href="source/fs/buffer.c#L127">127</a> <a name=L128 href="source/fs/buffer.c#L128">128</a> #define <a href="ident?i=_hashfn">_hashfn</a>(dev,block) (((unsigned)(dev^block))%<a href="ident?i=NR_HASH">NR_HASH</a>)<a name=L129 href="source/fs/buffer.c#L129">129</a> #define <a href="ident?i=hash">hash</a>(dev,block) <a href="ident?i=hash_table">hash_table</a>[<a href="ident?i=_hashfn">_hashfn</a>(dev,block)]<a name=L130 href="source/fs/buffer.c#L130">130</a> <a name=L131 href="source/fs/buffer.c#L131">131</a> static inline void <a href="ident?i=remove_from_queues">remove_from_queues</a>(struct <a href="ident?i=buffer_head">buffer_head</a> * bh)<a name=L132 href="source/fs/buffer.c#L132">132</a> {<a name=L133 href="source/fs/buffer.c#L133">133</a> <b><i>/* remove from hash-queue */</i></b><a name=L134 href="source/fs/buffer.c#L134">134</a> if (bh->b_next)<a name=L135 href="source/fs/buffer.c#L135">135</a> bh->b_next->b_prev = bh->b_prev;<a name=L136 href="source/fs/buffer.c#L136">136</a> if (bh->b_prev)<a name=L137 href="source/fs/buffer.c#L137">137</a> bh->b_prev->b_next = bh->b_next;<a name=L138 href="source/fs/buffer.c#L138">138</a> if (<a href="ident?i=hash">hash</a>(bh->b_dev,bh->b_blocknr) == bh)<a name=L139 href="source/fs/buffer.c#L139">139</a> <a href="ident?i=hash">hash</a>(bh->b_dev,bh->b_blocknr) = bh->b_next;<a name=L140 href="source/fs/buffer.c#L140">140</a> <b><i>/* remove from free list */</i></b><a name=L141 href="source/fs/buffer.c#L141">141</a> if (!(bh->b_prev_free) || !(bh->b_next_free))<a name=L142 href="source/fs/buffer.c#L142">142</a> <a href="ident?i=panic">panic</a>(<i>"Free block list corrupted"</i>);<a name=L143 href="source/fs/buffer.c#L143">143</a> bh->b_prev_free->b_next_free = bh->b_next_free;<a name=L144 href="source/fs/buffer.c#L144">144</a> bh->b_next_free->b_prev_free = bh->b_prev_free;<a name=L145 href="source/fs/buffer.c#L145">145</a> if (<a href="ident?i=free_list">free_list</a> == bh)<a name=L146 href="source/fs/buffer.c#L146">146</a> <a href="ident?i=free_list">free_list</a> = bh->b_next_free;<a name=L147 href="source/fs/buffer.c#L147">147</a> }<a name=L148 href="source/fs/buffer.c#L148">148</a> <a name=L149 href="source/fs/buffer.c#L149">149</a> static inline void <a href="ident?i=insert_into_queues">insert_into_queues</a>(struct <a href="ident?i=buffer_head">buffer_head</a> * bh)<a name=L150 href="source/fs/buffer.c#L150">150</a> {<a name=L151 href="source/fs/buffer.c#L151">151</a> <b><i>/* put at end of free list */</i></b><a name=L152 href="source/fs/buffer.c#L152">152</a> bh->b_next_free = <a href="ident?i=free_list">free_list</a>;<a name=L153 href="source/fs/buffer.c#L153">153</a> bh->b_prev_free = <a href="ident?i=free_list">free_list</a>->b_prev_free;<a name=L154 href="source/fs/buffer.c#L154">154</a> <a href="ident?i=free_list">free_list</a>->b_prev_free->b_next_free = bh;<a name=L155 href="source/fs/buffer.c#L155">155</a> <a href="ident?i=free_list">free_list</a>->b_prev_free = bh;<a name=L156 href="source/fs/buffer.c#L156">156</a> <b><i>/* put the buffer in new hash-queue if it has a device */</i></b><a name=L157 href="source/fs/buffer.c#L157">157</a> bh->b_prev = <a href="ident?i=NULL">NULL</a>;<a name=L158 href="source/fs/buffer.c#L158">158</a> bh->b_next = <a href="ident?i=NULL">NULL</a>;<a name=L159 href="source/fs/buffer.c#L159">159</a> if (!bh->b_dev)<a name=L160 href="source/fs/buffer.c#L160">160</a> return;<a name=L161 href="source/fs/buffer.c#L161">161</a> bh->b_next = <a href="ident?i=hash">hash</a>(bh->b_dev,bh->b_blocknr);<a name=L162 href="source/fs/buffer.c#L162">162</a> <a href="ident?i=hash">hash</a>(bh->b_dev,bh->b_blocknr) = bh;<a name=L163 href="source/fs/buffer.c#L163">163</a> bh->b_next->b_prev = bh;<a name=L164 href="source/fs/buffer.c#L164">164</a> }<a name=L165 href="source/fs/buffer.c#L165">165</a> <a name=L166 href="source/fs/buffer.c#L166">166</a> static struct <a href="ident?i=buffer_head">buffer_head</a> * <a href="ident?i=find_buffer">find_buffer</a>(int dev, int block)<a name=L167 href="source/fs/buffer.c#L167">167</a> { <a name=L168 href="source/fs/buffer.c#L168">168</a> struct <a href="ident?i=buffer_head">buffer_head</a> * tmp;<a name=L169 href="source/fs/buffer.c#L169">169</a> <a name=L170 href="source/fs/buffer.c#L170">170</a> for (tmp = <a href="ident?i=hash">hash</a>(dev,block) ; tmp != <a href="ident?i=NULL">NULL</a> ; tmp = tmp->b_next)<a name=L171 href="source/fs/buffer.c#L171">171</a> if (tmp->b_dev==dev && tmp->b_blocknr==block)<a name=L172 href="source/fs/buffer.c#L172">172</a> return tmp;<a name=L173 href="source/fs/buffer.c#L173">173</a> return <a href="ident?i=NULL">NULL</a>;<a name=L174 href="source/fs/buffer.c#L174">174</a> }<a name=L175 href="source/fs/buffer.c#L175">175</a> <a name=L176 href="source/fs/buffer.c#L176">176</a> <b><i>/*</i></b><a name=L177 href="source/fs/buffer.c#L177">177</a> <b><i> * Why like this, I hear you say... The reason is race-conditions.</i></b><a name=L178 href="source/fs/buffer.c#L178">178</a> <b><i> * As we don't lock buffers (unless we are readint them, that is),</i></b><a name=L179 href="source/fs/buffer.c#L179">179</a> <b><i> * something might happen to it while we sleep (ie a read-error</i></b><a name=L180 href="source/fs/buffer.c#L180">180</a> <b><i> * will force it bad). This shouldn't really happen currently, but</i></b><a name=L181 href="source/fs/buffer.c#L181">181</a> <b><i> * the code is ready.</i></b><a name=L182 href="source/fs/buffer.c#L182">182</a> <b><i> */</i></b><a name=L183 href="source/fs/buffer.c#L183">183</a> struct <a href="ident?i=buffer_head">buffer_head</a> * <a href="ident?i=get_hash_table">get_hash_table</a>(int dev, int block)<a name=L184 href="source/fs/buffer.c#L184">184</a> {<a name=L185 href="source/fs/buffer.c#L185">185</a> struct <a href="ident?i=buffer_head">buffer_head</a> * bh;<a name=L186 href="source/fs/buffer.c#L186">186</a> <a name=L187 href="source/fs/buffer.c#L187">187</a> for (;;) {<a name=L188 href="source/fs/buffer.c#L188">188</a> if (!(bh=<a href="ident?i=find_buffer">find_buffer</a>(dev,block)))<a name=L189 href="source/fs/buffer.c#L189">189</a> return <a href="ident?i=NULL">NULL</a>;<a name=L190 href="source/fs/buffer.c#L190">190</a> bh->b_count++;<a name=L191 href="source/fs/buffer.c#L191">191</a> <a href="ident?i=wait_on_buffer">wait_on_buffer</a>(bh);<a name=L192 href="source/fs/buffer.c#L192">192</a> if (bh->b_dev == dev && bh->b_blocknr == block)<a name=L193 href="source/fs/buffer.c#L193">193</a> return bh;<a name=L194 href="source/fs/buffer.c#L194">194</a> bh->b_count--;<a name=L195 href="source/fs/buffer.c#L195">195</a> }<a name=L196 href="source/fs/buffer.c#L196">196</a> }<a name=L197 href="source/fs/buffer.c#L197">197</a> <a name=L198 href="source/fs/buffer.c#L198">198</a> <b><i>/*</i></b><a name=L199 href="source/fs/buffer.c#L199">199</a> <b><i> * Ok, this is getblk, and it isn't very clear, again to hinder</i></b><a name=L200 href="source/fs/buffer.c#L200">200</a> <b><i> * race-conditions. Most of the code is seldom used, (ie repeating),</i></b><a name=L201 href="source/fs/buffer.c#L201">201</a> <b><i> * so it should be much more efficient than it looks.</i></b><a name=L202 href="source/fs/buffer.c#L202">202</a> <b><i> *</i></b><a name=L203 href="source/fs/buffer.c#L203">203</a> <b><i> * The algoritm is changed: hopefully better, and an elusive bug removed.</i></b><a name=L204 href="source/fs/buffer.c#L204">204</a> <b><i> */</i></b><a name=L205 href="source/fs/buffer.c#L205">205</a> #define <a href="ident?i=BADNESS">BADNESS</a>(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)<a name=L206 href="source/fs/buffer.c#L206">206</a> struct <a href="ident?i=buffer_head">buffer_head</a> * <a href="ident?i=getblk">getblk</a>(int dev,int block)<a name=L207 href="source/fs/buffer.c#L207">207</a> {<a name=L208 href="source/fs/buffer.c#L208">208</a> struct <a href="ident?i=buffer_head">buffer_head</a> * tmp, * bh;<a name=L209 href="source/fs/buffer.c#L209">209</a> <a name=L210 href="source/fs/buffer.c#L210">210</a> repeat:<a name=L211 href="source/fs/buffer.c#L211">211</a> if (bh = <a href="ident?i=get_hash_table">get_hash_table</a>(dev,block))<a name=L212 href="source/fs/buffer.c#L212">212</a> return bh;<a name=L213 href="source/fs/buffer.c#L213">213</a> tmp = <a href="ident?i=free_list">free_list</a>;<a name=L214 href="source/fs/buffer.c#L214">214</a> do {<a name=L215 href="source/fs/buffer.c#L215">215</a> if (tmp->b_count)<a name=L216 href="source/fs/buffer.c#L216">216</a> continue;<a name=L217 href="source/fs/buffer.c#L217">217</a> if (!bh || <a href="ident?i=BADNESS">BADNESS</a>(tmp)<<a href="ident?i=BADNESS">BADNESS</a>(bh)) {<a name=L218 href="source/fs/buffer.c#L218">218</a> bh = tmp;<a name=L219 href="source/fs/buffer.c#L219">219</a> if (!<a href="ident?i=BADNESS">BADNESS</a>(tmp))<a name=L220 href="source/fs/buffer.c#L220">220</a> break;<a name=L221 href="source/fs/buffer.c#L221">221</a> }<a name=L222 href="source/fs/buffer.c#L222">222</a> <b><i>/* and repeat until we find something good */</i></b><a name=L223 href="source/fs/buffer.c#L223">223</a> } while ((tmp = tmp->b_next_free) != <a href="ident?i=free_list">free_list</a>);<a name=L224 href="source/fs/buffer.c#L224">224</a> if (!bh) {<a name=L225 href="source/fs/buffer.c#L225">225</a> <a href="ident?i=sleep_on">sleep_on</a>(&<a href="ident?i=buffer_wait">buffer_wait</a>);<a name=L226 href="source/fs/buffer.c#L226">226</a> goto repeat;<a name=L227 href="source/fs/buffer.c#L227">227</a> }<a name=L228 href="source/fs/buffer.c#L228">228</a> <a href="ident?i=wait_on_buffer">wait_on_buffer</a>(bh);<a name=L229 href="source/fs/buffer.c#L229">229</a> if (bh->b_count)<a name=L230 href="source/fs/buffer.c#L230">230</a> goto repeat;<a name=L231 href="source/fs/buffer.c#L231">231</a> while (bh->b_dirt) {<a name=L232 href="source/fs/buffer.c#L232">232</a> <a href="ident?i=sync_dev">sync_dev</a>(bh->b_dev);<a name=L233 href="source/fs/buffer.c#L233">233</a> <a href="ident?i=wait_on_buffer">wait_on_buffer</a>(bh);<a name=L234 href="source/fs/buffer.c#L234">234</a> if (bh->b_count)<a name=L235 href="source/fs/buffer.c#L235">235</a> goto repeat;<a name=L236 href="source/fs/buffer.c#L236">236</a> }<a name=L237 href="source/fs/buffer.c#L237">237</a> <b><i>/* NOTE!! While we slept waiting for this block, somebody else might */</i></b><a name=L238 href="source/fs/buffer.c#L238">238</a> <b><i>/* already have added "this" block to the cache. check it */</i></b><a name=L239 href="source/fs/buffer.c#L239">239</a> if (<a href="ident?i=find_buffer">find_buffer</a>(dev,block))<a name=L240 href="source/fs/buffer.c#L240">240</a> goto repeat;<a name=L241 href="source/fs/buffer.c#L241">241</a> <b><i>/* OK, FINALLY we know that this buffer is the only one of it's kind, */</i></b><a name=L242 href="source/fs/buffer.c#L242">242</a> <b><i>/* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */</i></b><a name=L243 href="source/fs/buffer.c#L243">243</a> bh->b_count=1;<a name=L244 href="source/fs/buffer.c#L244">244</a> bh->b_dirt=0;<a name=L245 href="source/fs/buffer.c#L245">245</a> bh->b_uptodate=0;<a name=L246 href="source/fs/buffer.c#L246">246</a> <a href="ident?i=remove_from_queues">remove_from_queues</a>(bh);<a name=L247 href="source/fs/buffer.c#L247">247</a> bh->b_dev=dev;<a name=L248 href="source/fs/buffer.c#L248">248</a> bh->b_blocknr=block;<a name=L249 href="source/fs/buffer.c#L249">249</a> <a href="ident?i=insert_into_queues">insert_into_queues</a>(bh);<a name=L250 href="source/fs/buffer.c#L250">250</a> return bh;<a name=L251 href="source/fs/buffer.c#L251">251</a> }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -