1433d6423SLionel Sambuc /* This file is the counterpart of "read.c". It contains the code for writing
2433d6423SLionel Sambuc * insofar as this is not contained in fs_readwrite().
3433d6423SLionel Sambuc *
4433d6423SLionel Sambuc * The entry points into this file are
5433d6423SLionel Sambuc * write_map: write a new block into an inode
6433d6423SLionel Sambuc * new_block: acquire a new block
7433d6423SLionel Sambuc * zero_block: overwrite a block with zeroes
8433d6423SLionel Sambuc *
9433d6423SLionel Sambuc * Created (MFS based):
10433d6423SLionel Sambuc * February 2010 (Evgeniy Ivanov)
11433d6423SLionel Sambuc */
12433d6423SLionel Sambuc
13433d6423SLionel Sambuc #include "fs.h"
14433d6423SLionel Sambuc #include <string.h>
15433d6423SLionel Sambuc #include <assert.h>
16433d6423SLionel Sambuc #include <sys/param.h>
17433d6423SLionel Sambuc #include "buf.h"
18433d6423SLionel Sambuc #include "inode.h"
19433d6423SLionel Sambuc #include "super.h"
20433d6423SLionel Sambuc
21433d6423SLionel Sambuc static void wr_indir(struct buf *bp, int index, block_t block);
22433d6423SLionel Sambuc static int empty_indir(struct buf *, struct super_block *);
23433d6423SLionel Sambuc
24433d6423SLionel Sambuc /*===========================================================================*
25433d6423SLionel Sambuc * write_map *
26433d6423SLionel Sambuc *===========================================================================*/
write_map(rip,position,new_wblock,op)27433d6423SLionel Sambuc int write_map(rip, position, new_wblock, op)
28433d6423SLionel Sambuc struct inode *rip; /* pointer to inode to be changed */
29433d6423SLionel Sambuc off_t position; /* file address to be mapped */
30433d6423SLionel Sambuc block_t new_wblock; /* block # to be inserted */
31433d6423SLionel Sambuc int op; /* special actions */
32433d6423SLionel Sambuc {
33433d6423SLionel Sambuc /* Write a new block into an inode.
34433d6423SLionel Sambuc *
35433d6423SLionel Sambuc * If op includes WMAP_FREE, free the block corresponding to that position
36433d6423SLionel Sambuc * in the inode ('new_wblock' is ignored then). Also free the indirect block
37433d6423SLionel Sambuc * if that was the last entry in the indirect block.
38433d6423SLionel Sambuc * Also free the double/triple indirect block if that was the last entry in
39433d6423SLionel Sambuc * the double/triple indirect block.
40433d6423SLionel Sambuc * It's the only function which should take care about rip->i_blocks counter.
41433d6423SLionel Sambuc */
42433d6423SLionel Sambuc int index1 = 0, index2 = 0, index3 = 0; /* indexes in single..triple indirect blocks */
43433d6423SLionel Sambuc long excess, block_pos;
44433d6423SLionel Sambuc char new_ind = 0, new_dbl = 0, new_triple = 0;
45433d6423SLionel Sambuc int single = 0, triple = 0;
46433d6423SLionel Sambuc block_t old_block = NO_BLOCK, b1 = NO_BLOCK, b2 = NO_BLOCK, b3 = NO_BLOCK;
47433d6423SLionel Sambuc struct buf *bp = NULL,
48433d6423SLionel Sambuc *bp_dindir = NULL,
49433d6423SLionel Sambuc *bp_tindir = NULL;
50433d6423SLionel Sambuc static char first_time = TRUE;
51433d6423SLionel Sambuc static long addr_in_block;
52433d6423SLionel Sambuc static long addr_in_block2;
53433d6423SLionel Sambuc static long doub_ind_s;
54433d6423SLionel Sambuc static long triple_ind_s;
55433d6423SLionel Sambuc static long out_range_s;
56433d6423SLionel Sambuc
57433d6423SLionel Sambuc if (first_time) {
58433d6423SLionel Sambuc addr_in_block = rip->i_sp->s_block_size / BLOCK_ADDRESS_BYTES;
59433d6423SLionel Sambuc addr_in_block2 = addr_in_block * addr_in_block;
60433d6423SLionel Sambuc doub_ind_s = EXT2_NDIR_BLOCKS + addr_in_block;
61433d6423SLionel Sambuc triple_ind_s = doub_ind_s + addr_in_block2;
62433d6423SLionel Sambuc out_range_s = triple_ind_s + addr_in_block2 * addr_in_block;
63433d6423SLionel Sambuc first_time = FALSE;
64433d6423SLionel Sambuc }
65433d6423SLionel Sambuc
66433d6423SLionel Sambuc block_pos = position / rip->i_sp->s_block_size; /* relative blk # in file */
67433d6423SLionel Sambuc rip->i_dirt = IN_DIRTY; /* inode will be changed */
68433d6423SLionel Sambuc
69433d6423SLionel Sambuc /* Is 'position' to be found in the inode itself? */
70433d6423SLionel Sambuc if (block_pos < EXT2_NDIR_BLOCKS) {
71433d6423SLionel Sambuc if (rip->i_block[block_pos] != NO_BLOCK && (op & WMAP_FREE)) {
72433d6423SLionel Sambuc free_block(rip->i_sp, rip->i_block[block_pos]);
73433d6423SLionel Sambuc rip->i_block[block_pos] = NO_BLOCK;
74433d6423SLionel Sambuc rip->i_blocks -= rip->i_sp->s_sectors_in_block;
75433d6423SLionel Sambuc } else {
76433d6423SLionel Sambuc rip->i_block[block_pos] = new_wblock;
77433d6423SLionel Sambuc rip->i_blocks += rip->i_sp->s_sectors_in_block;
78433d6423SLionel Sambuc }
79433d6423SLionel Sambuc return(OK);
80433d6423SLionel Sambuc }
81433d6423SLionel Sambuc
82433d6423SLionel Sambuc /* It is not in the inode, so it must be single, double or triple indirect */
83433d6423SLionel Sambuc if (block_pos < doub_ind_s) {
84433d6423SLionel Sambuc b1 = rip->i_block[EXT2_NDIR_BLOCKS]; /* addr of single indirect block */
85433d6423SLionel Sambuc index1 = block_pos - EXT2_NDIR_BLOCKS;
86433d6423SLionel Sambuc single = TRUE;
87433d6423SLionel Sambuc } else if (block_pos >= out_range_s) { /* TODO: do we need it? */
88433d6423SLionel Sambuc return(EFBIG);
89433d6423SLionel Sambuc } else {
90433d6423SLionel Sambuc /* double or triple indirect block. At first if it's triple,
91433d6423SLionel Sambuc * find double indirect block.
92433d6423SLionel Sambuc */
93433d6423SLionel Sambuc excess = block_pos - doub_ind_s;
94433d6423SLionel Sambuc b2 = rip->i_block[EXT2_DIND_BLOCK];
95433d6423SLionel Sambuc if (block_pos >= triple_ind_s) {
96433d6423SLionel Sambuc b3 = rip->i_block[EXT2_TIND_BLOCK];
97433d6423SLionel Sambuc if (b3 == NO_BLOCK && !(op & WMAP_FREE)) {
98433d6423SLionel Sambuc /* Create triple indirect block. */
99433d6423SLionel Sambuc if ( (b3 = alloc_block(rip, rip->i_bsearch) ) == NO_BLOCK) {
100433d6423SLionel Sambuc ext2_debug("failed to allocate tblock near %d\n", rip->i_block[0]);
101433d6423SLionel Sambuc return(ENOSPC);
102433d6423SLionel Sambuc }
103433d6423SLionel Sambuc rip->i_block[EXT2_TIND_BLOCK] = b3;
104433d6423SLionel Sambuc rip->i_blocks += rip->i_sp->s_sectors_in_block;
105433d6423SLionel Sambuc new_triple = TRUE;
106433d6423SLionel Sambuc }
107433d6423SLionel Sambuc /* 'b3' is block number for triple indirect block, either old
108433d6423SLionel Sambuc * or newly created.
109433d6423SLionel Sambuc * If there wasn't one and WMAP_FREE is set, 'b3' is NO_BLOCK.
110433d6423SLionel Sambuc */
111433d6423SLionel Sambuc if (b3 == NO_BLOCK && (op & WMAP_FREE)) {
112433d6423SLionel Sambuc /* WMAP_FREE and no triple indirect block - then no
113433d6423SLionel Sambuc * double and single indirect blocks either.
114433d6423SLionel Sambuc */
115433d6423SLionel Sambuc b1 = b2 = NO_BLOCK;
116433d6423SLionel Sambuc } else {
117433d6423SLionel Sambuc bp_tindir = get_block(rip->i_dev, b3, (new_triple ? NO_READ : NORMAL));
118433d6423SLionel Sambuc if (new_triple) {
119433d6423SLionel Sambuc zero_block(bp_tindir);
120433d6423SLionel Sambuc lmfs_markdirty(bp_tindir);
121433d6423SLionel Sambuc }
122433d6423SLionel Sambuc excess = block_pos - triple_ind_s;
123433d6423SLionel Sambuc index3 = excess / addr_in_block2;
124433d6423SLionel Sambuc b2 = rd_indir(bp_tindir, index3);
125433d6423SLionel Sambuc excess = excess % addr_in_block2;
126433d6423SLionel Sambuc }
127433d6423SLionel Sambuc triple = TRUE;
128433d6423SLionel Sambuc }
129433d6423SLionel Sambuc
130433d6423SLionel Sambuc if (b2 == NO_BLOCK && !(op & WMAP_FREE)) {
131433d6423SLionel Sambuc /* Create the double indirect block. */
132433d6423SLionel Sambuc if ( (b2 = alloc_block(rip, rip->i_bsearch) ) == NO_BLOCK) {
133433d6423SLionel Sambuc /* Release triple ind blk. */
1340314acfbSDavid van Moolenbroek put_block(bp_tindir);
135433d6423SLionel Sambuc ext2_debug("failed to allocate dblock near %d\n", rip->i_block[0]);
136433d6423SLionel Sambuc return(ENOSPC);
137433d6423SLionel Sambuc }
138433d6423SLionel Sambuc if (triple) {
139433d6423SLionel Sambuc wr_indir(bp_tindir, index3, b2); /* update triple indir */
140433d6423SLionel Sambuc lmfs_markdirty(bp_tindir);
141433d6423SLionel Sambuc } else {
142433d6423SLionel Sambuc rip->i_block[EXT2_DIND_BLOCK] = b2;
143433d6423SLionel Sambuc }
144433d6423SLionel Sambuc rip->i_blocks += rip->i_sp->s_sectors_in_block;
145433d6423SLionel Sambuc new_dbl = TRUE; /* set flag for later */
146433d6423SLionel Sambuc }
147433d6423SLionel Sambuc
148433d6423SLionel Sambuc /* 'b2' is block number for double indirect block, either old
149433d6423SLionel Sambuc * or newly created.
150433d6423SLionel Sambuc * If there wasn't one and WMAP_FREE is set, 'b2' is NO_BLOCK.
151433d6423SLionel Sambuc */
152433d6423SLionel Sambuc if (b2 == NO_BLOCK && (op & WMAP_FREE)) {
153433d6423SLionel Sambuc /* WMAP_FREE and no double indirect block - then no
154433d6423SLionel Sambuc * single indirect block either.
155433d6423SLionel Sambuc */
156433d6423SLionel Sambuc b1 = NO_BLOCK;
157433d6423SLionel Sambuc } else {
158433d6423SLionel Sambuc bp_dindir = get_block(rip->i_dev, b2, (new_dbl ? NO_READ : NORMAL));
159433d6423SLionel Sambuc if (new_dbl) {
160433d6423SLionel Sambuc zero_block(bp_dindir);
161433d6423SLionel Sambuc lmfs_markdirty(bp_dindir);
162433d6423SLionel Sambuc }
163433d6423SLionel Sambuc index2 = excess / addr_in_block;
164433d6423SLionel Sambuc b1 = rd_indir(bp_dindir, index2);
165433d6423SLionel Sambuc index1 = excess % addr_in_block;
166433d6423SLionel Sambuc }
167433d6423SLionel Sambuc single = FALSE;
168433d6423SLionel Sambuc }
169433d6423SLionel Sambuc
170433d6423SLionel Sambuc /* b1 is now single indirect block or NO_BLOCK; 'index' is index.
171433d6423SLionel Sambuc * We have to create the indirect block if it's NO_BLOCK. Unless
172433d6423SLionel Sambuc * we're freing (WMAP_FREE).
173433d6423SLionel Sambuc */
174433d6423SLionel Sambuc if (b1 == NO_BLOCK && !(op & WMAP_FREE)) {
175433d6423SLionel Sambuc if ( (b1 = alloc_block(rip, rip->i_bsearch) ) == NO_BLOCK) {
176433d6423SLionel Sambuc /* Release dbl and triple indirect blks. */
1770314acfbSDavid van Moolenbroek put_block(bp_dindir);
1780314acfbSDavid van Moolenbroek put_block(bp_tindir);
179433d6423SLionel Sambuc ext2_debug("failed to allocate dblock near %d\n", rip->i_block[0]);
180433d6423SLionel Sambuc return(ENOSPC);
181433d6423SLionel Sambuc }
182433d6423SLionel Sambuc if (single) {
183433d6423SLionel Sambuc rip->i_block[EXT2_NDIR_BLOCKS] = b1; /* update inode single indirect */
184433d6423SLionel Sambuc } else {
185433d6423SLionel Sambuc wr_indir(bp_dindir, index2, b1); /* update dbl indir */
186433d6423SLionel Sambuc lmfs_markdirty(bp_dindir);
187433d6423SLionel Sambuc }
188433d6423SLionel Sambuc rip->i_blocks += rip->i_sp->s_sectors_in_block;
189433d6423SLionel Sambuc new_ind = TRUE;
190433d6423SLionel Sambuc }
191433d6423SLionel Sambuc
192433d6423SLionel Sambuc /* b1 is indirect block's number (unless it's NO_BLOCK when we're
193433d6423SLionel Sambuc * freeing).
194433d6423SLionel Sambuc */
195433d6423SLionel Sambuc if (b1 != NO_BLOCK) {
196433d6423SLionel Sambuc bp = get_block(rip->i_dev, b1, (new_ind ? NO_READ : NORMAL) );
197433d6423SLionel Sambuc if (new_ind)
198433d6423SLionel Sambuc zero_block(bp);
199433d6423SLionel Sambuc if (op & WMAP_FREE) {
200433d6423SLionel Sambuc if ((old_block = rd_indir(bp, index1)) != NO_BLOCK) {
201433d6423SLionel Sambuc free_block(rip->i_sp, old_block);
202433d6423SLionel Sambuc rip->i_blocks -= rip->i_sp->s_sectors_in_block;
203433d6423SLionel Sambuc wr_indir(bp, index1, NO_BLOCK);
204433d6423SLionel Sambuc }
205433d6423SLionel Sambuc
206433d6423SLionel Sambuc /* Last reference in the indirect block gone? Then
207433d6423SLionel Sambuc * free the indirect block.
208433d6423SLionel Sambuc */
209433d6423SLionel Sambuc if (empty_indir(bp, rip->i_sp)) {
210433d6423SLionel Sambuc free_block(rip->i_sp, b1);
211433d6423SLionel Sambuc rip->i_blocks -= rip->i_sp->s_sectors_in_block;
212433d6423SLionel Sambuc b1 = NO_BLOCK;
213433d6423SLionel Sambuc /* Update the reference to the indirect block to
214433d6423SLionel Sambuc * NO_BLOCK - in the double indirect block if there
215433d6423SLionel Sambuc * is one, otherwise in the inode directly.
216433d6423SLionel Sambuc */
217433d6423SLionel Sambuc if (single) {
218433d6423SLionel Sambuc rip->i_block[EXT2_NDIR_BLOCKS] = b1;
219433d6423SLionel Sambuc } else {
220433d6423SLionel Sambuc wr_indir(bp_dindir, index2, b1);
221433d6423SLionel Sambuc lmfs_markdirty(bp_dindir);
222433d6423SLionel Sambuc }
223433d6423SLionel Sambuc }
224433d6423SLionel Sambuc } else {
225433d6423SLionel Sambuc wr_indir(bp, index1, new_wblock);
226433d6423SLionel Sambuc rip->i_blocks += rip->i_sp->s_sectors_in_block;
227433d6423SLionel Sambuc }
228433d6423SLionel Sambuc /* b1 equals NO_BLOCK only when we are freeing up the indirect block. */
229e94f856bSDavid van Moolenbroek if(b1 != NO_BLOCK)
230433d6423SLionel Sambuc lmfs_markdirty(bp);
2310314acfbSDavid van Moolenbroek put_block(bp);
232433d6423SLionel Sambuc }
233433d6423SLionel Sambuc
234433d6423SLionel Sambuc /* If the single indirect block isn't there (or was just freed),
235433d6423SLionel Sambuc * see if we have to keep the double indirect block, if any.
236433d6423SLionel Sambuc */
237433d6423SLionel Sambuc if (b1 == NO_BLOCK && !single && b2 != NO_BLOCK &&
238433d6423SLionel Sambuc empty_indir(bp_dindir, rip->i_sp)) {
239433d6423SLionel Sambuc free_block(rip->i_sp, b2);
240433d6423SLionel Sambuc rip->i_blocks -= rip->i_sp->s_sectors_in_block;
241433d6423SLionel Sambuc b2 = NO_BLOCK;
242433d6423SLionel Sambuc if (triple) {
243433d6423SLionel Sambuc wr_indir(bp_tindir, index3, b2); /* update triple indir */
244433d6423SLionel Sambuc lmfs_markdirty(bp_tindir);
245433d6423SLionel Sambuc } else {
246433d6423SLionel Sambuc rip->i_block[EXT2_DIND_BLOCK] = b2;
247433d6423SLionel Sambuc }
248433d6423SLionel Sambuc }
249433d6423SLionel Sambuc /* If the double indirect block isn't there (or was just freed),
250433d6423SLionel Sambuc * see if we have to keep the triple indirect block, if any.
251433d6423SLionel Sambuc */
252433d6423SLionel Sambuc if (b2 == NO_BLOCK && triple && b3 != NO_BLOCK &&
253433d6423SLionel Sambuc empty_indir(bp_tindir, rip->i_sp)) {
254433d6423SLionel Sambuc free_block(rip->i_sp, b3);
255433d6423SLionel Sambuc rip->i_blocks -= rip->i_sp->s_sectors_in_block;
256433d6423SLionel Sambuc rip->i_block[EXT2_TIND_BLOCK] = NO_BLOCK;
257433d6423SLionel Sambuc }
258433d6423SLionel Sambuc
2590314acfbSDavid van Moolenbroek put_block(bp_dindir); /* release double indirect blk */
2600314acfbSDavid van Moolenbroek put_block(bp_tindir); /* release triple indirect blk */
261433d6423SLionel Sambuc
262433d6423SLionel Sambuc return(OK);
263433d6423SLionel Sambuc }
264433d6423SLionel Sambuc
265433d6423SLionel Sambuc
266433d6423SLionel Sambuc /*===========================================================================*
267433d6423SLionel Sambuc * wr_indir *
268433d6423SLionel Sambuc *===========================================================================*/
wr_indir(bp,wrindex,block)269433d6423SLionel Sambuc static void wr_indir(bp, wrindex, block)
270433d6423SLionel Sambuc struct buf *bp; /* pointer to indirect block */
271433d6423SLionel Sambuc int wrindex; /* index into *bp */
272433d6423SLionel Sambuc block_t block; /* block to write */
273433d6423SLionel Sambuc {
274433d6423SLionel Sambuc /* Given a pointer to an indirect block, write one entry. */
275433d6423SLionel Sambuc
276433d6423SLionel Sambuc if(bp == NULL)
277433d6423SLionel Sambuc panic("wr_indir() on NULL");
278433d6423SLionel Sambuc
279433d6423SLionel Sambuc /* write a block into an indirect block */
280433d6423SLionel Sambuc b_ind(bp)[wrindex] = conv4(le_CPU, block);
281433d6423SLionel Sambuc }
282433d6423SLionel Sambuc
283433d6423SLionel Sambuc
284433d6423SLionel Sambuc /*===========================================================================*
285433d6423SLionel Sambuc * empty_indir *
286433d6423SLionel Sambuc *===========================================================================*/
empty_indir(bp,sb)287433d6423SLionel Sambuc static int empty_indir(bp, sb)
288433d6423SLionel Sambuc struct buf *bp; /* pointer to indirect block */
289433d6423SLionel Sambuc struct super_block *sb; /* superblock of device block resides on */
290433d6423SLionel Sambuc {
291433d6423SLionel Sambuc /* Return nonzero if the indirect block pointed to by bp contains
292433d6423SLionel Sambuc * only NO_BLOCK entries.
293433d6423SLionel Sambuc */
294433d6423SLionel Sambuc long addr_in_block = sb->s_block_size/4; /* 4 bytes per addr */
295433d6423SLionel Sambuc int i;
296433d6423SLionel Sambuc for(i = 0; i < addr_in_block; i++)
297433d6423SLionel Sambuc if(b_ind(bp)[i] != NO_BLOCK)
298433d6423SLionel Sambuc return(0);
299433d6423SLionel Sambuc return(1);
300433d6423SLionel Sambuc }
301433d6423SLionel Sambuc
302433d6423SLionel Sambuc /*===========================================================================*
303433d6423SLionel Sambuc * new_block *
304433d6423SLionel Sambuc *===========================================================================*/
new_block(rip,position)305433d6423SLionel Sambuc struct buf *new_block(rip, position)
306433d6423SLionel Sambuc register struct inode *rip; /* pointer to inode */
307433d6423SLionel Sambuc off_t position; /* file pointer */
308433d6423SLionel Sambuc {
309433d6423SLionel Sambuc /* Acquire a new block and return a pointer to it. */
310*6c46a77dSDavid van Moolenbroek struct buf *bp;
311433d6423SLionel Sambuc int r;
312433d6423SLionel Sambuc block_t b;
313433d6423SLionel Sambuc
314433d6423SLionel Sambuc /* Is another block available? */
315433d6423SLionel Sambuc if ( (b = read_map(rip, position, 0)) == NO_BLOCK) {
316433d6423SLionel Sambuc /* Check if this position follows last allocated
317433d6423SLionel Sambuc * block.
318433d6423SLionel Sambuc */
319433d6423SLionel Sambuc block_t goal = NO_BLOCK;
320433d6423SLionel Sambuc if (rip->i_last_pos_bl_alloc != 0) {
321433d6423SLionel Sambuc off_t position_diff = position - rip->i_last_pos_bl_alloc;
322433d6423SLionel Sambuc if (rip->i_bsearch == 0) {
323433d6423SLionel Sambuc /* Should never happen, but not critical */
324433d6423SLionel Sambuc ext2_debug("warning, i_bsearch is 0, while\
325433d6423SLionel Sambuc i_last_pos_bl_alloc is not!");
326433d6423SLionel Sambuc }
327433d6423SLionel Sambuc if (position_diff <= rip->i_sp->s_block_size) {
328433d6423SLionel Sambuc goal = rip->i_bsearch + 1;
329433d6423SLionel Sambuc } else {
330433d6423SLionel Sambuc /* Non-sequential write operation,
331433d6423SLionel Sambuc * disable preallocation
332433d6423SLionel Sambuc * for this inode.
333433d6423SLionel Sambuc */
334433d6423SLionel Sambuc rip->i_preallocation = 0;
335433d6423SLionel Sambuc discard_preallocated_blocks(rip);
336433d6423SLionel Sambuc }
337433d6423SLionel Sambuc }
338433d6423SLionel Sambuc
339433d6423SLionel Sambuc if ( (b = alloc_block(rip, goal) ) == NO_BLOCK) {
340433d6423SLionel Sambuc err_code = ENOSPC;
341433d6423SLionel Sambuc return(NULL);
342433d6423SLionel Sambuc }
343433d6423SLionel Sambuc if ( (r = write_map(rip, position, b, 0)) != OK) {
344433d6423SLionel Sambuc free_block(rip->i_sp, b);
345433d6423SLionel Sambuc err_code = r;
346433d6423SLionel Sambuc ext2_debug("write_map failed\n");
347433d6423SLionel Sambuc return(NULL);
348433d6423SLionel Sambuc }
349433d6423SLionel Sambuc rip->i_last_pos_bl_alloc = position;
350433d6423SLionel Sambuc if (position == 0) {
351433d6423SLionel Sambuc /* rip->i_last_pos_bl_alloc points to the block position,
352433d6423SLionel Sambuc * and zero indicates first usage, thus just increment.
353433d6423SLionel Sambuc */
354433d6423SLionel Sambuc rip->i_last_pos_bl_alloc++;
355433d6423SLionel Sambuc }
356433d6423SLionel Sambuc }
357433d6423SLionel Sambuc
358*6c46a77dSDavid van Moolenbroek r = lmfs_get_block_ino(&bp, rip->i_dev, b, NO_READ, rip->i_num,
359433d6423SLionel Sambuc rounddown(position, rip->i_sp->s_block_size));
360*6c46a77dSDavid van Moolenbroek if (r != OK)
361*6c46a77dSDavid van Moolenbroek panic("ext2: error getting block (%llu,%u): %d", rip->i_dev, b, r);
362433d6423SLionel Sambuc zero_block(bp);
363433d6423SLionel Sambuc return(bp);
364433d6423SLionel Sambuc }
365433d6423SLionel Sambuc
366433d6423SLionel Sambuc /*===========================================================================*
367433d6423SLionel Sambuc * zero_block *
368433d6423SLionel Sambuc *===========================================================================*/
zero_block(bp)369433d6423SLionel Sambuc void zero_block(bp)
370433d6423SLionel Sambuc register struct buf *bp; /* pointer to buffer to zero */
371433d6423SLionel Sambuc {
372433d6423SLionel Sambuc /* Zero a block. */
373433d6423SLionel Sambuc ASSERT(bp->data);
3740314acfbSDavid van Moolenbroek memset(b_data(bp), 0, lmfs_fs_block_size());
375433d6423SLionel Sambuc lmfs_markdirty(bp);
376433d6423SLionel Sambuc }
377