Deleted Added
full compact
ffs_softdep.c (92462) ffs_softdep.c (92728)
1/*
2 * Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved.
3 *
4 * The soft updates code is derived from the appendix of a University
5 * of Michigan technical report (Gregory R. Ganger and Yale N. Patt,
6 * "Soft Updates: A Solution to the Metadata Update Problem in File
7 * Systems", CSE-TR-254-95, August 1995).
8 *

--- 25 unchanged lines hidden (view full) ---

34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: @(#)ffs_softdep.c 9.59 (McKusick) 6/21/00
39 */
40
41#include <sys/cdefs.h>
1/*
2 * Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved.
3 *
4 * The soft updates code is derived from the appendix of a University
5 * of Michigan technical report (Gregory R. Ganger and Yale N. Patt,
6 * "Soft Updates: A Solution to the Metadata Update Problem in File
7 * Systems", CSE-TR-254-95, August 1995).
8 *

--- 25 unchanged lines hidden (view full) ---

34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: @(#)ffs_softdep.c 9.59 (McKusick) 6/21/00
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/sys/ufs/ffs/ffs_softdep.c 92462 2002-03-17 01:25:47Z mckusick $");
42__FBSDID("$FreeBSD: head/sys/ufs/ffs/ffs_softdep.c 92728 2002-03-19 22:40:48Z alfred $");
43
44/*
45 * For now we want the safety net that the DIAGNOSTIC and DEBUG flags provide.
46 */
47#ifndef DIAGNOSTIC
48#define DIAGNOSTIC
49#endif
50#ifndef DEBUG

--- 92 unchanged lines hidden (view full) ---

143 ((unsigned)(type) < D_LAST ? memtype[type]->ks_shortdesc : "???")
144/*
145 * End system adaptaion definitions.
146 */
147
148/*
149 * Internal function prototypes.
150 */
43
44/*
45 * For now we want the safety net that the DIAGNOSTIC and DEBUG flags provide.
46 */
47#ifndef DIAGNOSTIC
48#define DIAGNOSTIC
49#endif
50#ifndef DEBUG

--- 92 unchanged lines hidden (view full) ---

143 ((unsigned)(type) < D_LAST ? memtype[type]->ks_shortdesc : "???")
144/*
145 * End system adaptaion definitions.
146 */
147
148/*
149 * Internal function prototypes.
150 */
151static void softdep_error __P((char *, int));
152static void drain_output __P((struct vnode *, int));
153static int getdirtybuf __P((struct buf **, int));
154static void clear_remove __P((struct thread *));
155static void clear_inodedeps __P((struct thread *));
156static int flush_pagedep_deps __P((struct vnode *, struct mount *,
157 struct diraddhd *));
158static int flush_inodedep_deps __P((struct fs *, ino_t));
159static int handle_written_filepage __P((struct pagedep *, struct buf *));
160static void diradd_inode_written __P((struct diradd *, struct inodedep *));
161static int handle_written_inodeblock __P((struct inodedep *, struct buf *));
162static void handle_allocdirect_partdone __P((struct allocdirect *));
163static void handle_allocindir_partdone __P((struct allocindir *));
164static void initiate_write_filepage __P((struct pagedep *, struct buf *));
165static void handle_written_mkdir __P((struct mkdir *, int));
166static void initiate_write_inodeblock __P((struct inodedep *, struct buf *));
167static void handle_workitem_freefile __P((struct freefile *));
168static void handle_workitem_remove __P((struct dirrem *, struct vnode *));
169static struct dirrem *newdirrem __P((struct buf *, struct inode *,
170 struct inode *, int, struct dirrem **));
171static void free_diradd __P((struct diradd *));
172static void free_allocindir __P((struct allocindir *, struct inodedep *));
173static void free_newdirblk __P((struct newdirblk *));
174static int indir_trunc __P((struct freeblks *, ufs_daddr_t, int, ufs_lbn_t,
175 long *));
176static void deallocate_dependencies __P((struct buf *, struct inodedep *));
177static void free_allocdirect __P((struct allocdirectlst *,
178 struct allocdirect *, int));
179static int check_inode_unwritten __P((struct inodedep *));
180static int free_inodedep __P((struct inodedep *));
181static void handle_workitem_freeblocks __P((struct freeblks *, int));
182static void merge_inode_lists __P((struct inodedep *));
183static void setup_allocindir_phase2 __P((struct buf *, struct inode *,
184 struct allocindir *));
185static struct allocindir *newallocindir __P((struct inode *, int, ufs_daddr_t,
186 ufs_daddr_t));
187static void handle_workitem_freefrag __P((struct freefrag *));
188static struct freefrag *newfreefrag __P((struct inode *, ufs_daddr_t, long));
189static void allocdirect_merge __P((struct allocdirectlst *,
190 struct allocdirect *, struct allocdirect *));
191static struct bmsafemap *bmsafemap_lookup __P((struct buf *));
192static int newblk_lookup __P((struct fs *, ufs_daddr_t, int,
193 struct newblk **));
194static int inodedep_lookup __P((struct fs *, ino_t, int, struct inodedep **));
195static int pagedep_lookup __P((struct inode *, ufs_lbn_t, int,
196 struct pagedep **));
197static void pause_timer __P((void *));
198static int request_cleanup __P((int, int));
199static int process_worklist_item __P((struct mount *, int));
200static void add_to_worklist __P((struct worklist *));
151static void softdep_error(char *, int);
152static void drain_output(struct vnode *, int);
153static int getdirtybuf(struct buf **, int);
154static void clear_remove(struct thread *);
155static void clear_inodedeps(struct thread *);
156static int flush_pagedep_deps(struct vnode *, struct mount *,
157 struct diraddhd *);
158static int flush_inodedep_deps(struct fs *, ino_t);
159static int handle_written_filepage(struct pagedep *, struct buf *);
160static void diradd_inode_written(struct diradd *, struct inodedep *);
161static int handle_written_inodeblock(struct inodedep *, struct buf *);
162static void handle_allocdirect_partdone(struct allocdirect *);
163static void handle_allocindir_partdone(struct allocindir *);
164static void initiate_write_filepage(struct pagedep *, struct buf *);
165static void handle_written_mkdir(struct mkdir *, int);
166static void initiate_write_inodeblock(struct inodedep *, struct buf *);
167static void handle_workitem_freefile(struct freefile *);
168static void handle_workitem_remove(struct dirrem *, struct vnode *);
169static struct dirrem *newdirrem(struct buf *, struct inode *,
170 struct inode *, int, struct dirrem **);
171static void free_diradd(struct diradd *);
172static void free_allocindir(struct allocindir *, struct inodedep *);
173static void free_newdirblk(struct newdirblk *);
174static int indir_trunc(struct freeblks *, ufs_daddr_t, int, ufs_lbn_t, long *);
175static void deallocate_dependencies(struct buf *, struct inodedep *);
176static void free_allocdirect(struct allocdirectlst *,
177 struct allocdirect *, int);
178static int check_inode_unwritten(struct inodedep *);
179static int free_inodedep(struct inodedep *);
180static void handle_workitem_freeblocks(struct freeblks *, int);
181static void merge_inode_lists(struct inodedep *);
182static void setup_allocindir_phase2(struct buf *, struct inode *,
183 struct allocindir *);
184static struct allocindir *newallocindir(struct inode *, int, ufs_daddr_t,
185 ufs_daddr_t);
186static void handle_workitem_freefrag(struct freefrag *);
187static struct freefrag *newfreefrag(struct inode *, ufs_daddr_t, long);
188static void allocdirect_merge(struct allocdirectlst *,
189 struct allocdirect *, struct allocdirect *);
190static struct bmsafemap *bmsafemap_lookup(struct buf *);
191static int newblk_lookup(struct fs *, ufs_daddr_t, int, struct newblk **);
192static int inodedep_lookup(struct fs *, ino_t, int, struct inodedep **);
193static int pagedep_lookup(struct inode *, ufs_lbn_t, int, struct pagedep **);
194static void pause_timer(void *);
195static int request_cleanup(int, int);
196static int process_worklist_item(struct mount *, int);
197static void add_to_worklist(struct worklist *);
201
202/*
203 * Exported softdep operations.
204 */
198
199/*
200 * Exported softdep operations.
201 */
205static void softdep_disk_io_initiation __P((struct buf *));
206static void softdep_disk_write_complete __P((struct buf *));
207static void softdep_deallocate_dependencies __P((struct buf *));
208static void softdep_move_dependencies __P((struct buf *, struct buf *));
209static int softdep_count_dependencies __P((struct buf *bp, int));
202static void softdep_disk_io_initiation(struct buf *);
203static void softdep_disk_write_complete(struct buf *);
204static void softdep_deallocate_dependencies(struct buf *);
205static void softdep_move_dependencies(struct buf *, struct buf *);
206static int softdep_count_dependencies(struct buf *bp, int);
210
211/*
212 * Locking primitives.
213 *
214 * For a uniprocessor, all we need to do is protect against disk
215 * interrupts. For a multiprocessor, this lock would have to be
216 * a mutex. A single mutex is used throughout this file, though
217 * finer grain locking could be used if contention warranted it.

--- 16 unchanged lines hidden (view full) ---

234#define NOHOLDER ((struct thread *)-1)
235#define SPECIAL_FLAG ((struct thread *)-2)
236static struct lockit {
237 int lkt_spl;
238 struct thread *lkt_held;
239} lk = { 0, NOHOLDER };
240static int lockcnt;
241
207
208/*
209 * Locking primitives.
210 *
211 * For a uniprocessor, all we need to do is protect against disk
212 * interrupts. For a multiprocessor, this lock would have to be
213 * a mutex. A single mutex is used throughout this file, though
214 * finer grain locking could be used if contention warranted it.

--- 16 unchanged lines hidden (view full) ---

231#define NOHOLDER ((struct thread *)-1)
232#define SPECIAL_FLAG ((struct thread *)-2)
233static struct lockit {
234 int lkt_spl;
235 struct thread *lkt_held;
236} lk = { 0, NOHOLDER };
237static int lockcnt;
238
242static void acquire_lock __P((struct lockit *));
243static void free_lock __P((struct lockit *));
244void softdep_panic __P((char *));
239static void acquire_lock(struct lockit *);
240static void free_lock(struct lockit *);
241void softdep_panic(char *);
245
246#define ACQUIRE_LOCK(lk) acquire_lock(lk)
247#define FREE_LOCK(lk) free_lock(lk)
248
249static void
250acquire_lock(lk)
251 struct lockit *lk;
252{

--- 32 unchanged lines hidden (view full) ---

285{
286
287 if (lk.lkt_held != NOHOLDER)
288 FREE_LOCK(&lk);
289 panic(msg);
290}
291#endif /* DEBUG */
292
242
243#define ACQUIRE_LOCK(lk) acquire_lock(lk)
244#define FREE_LOCK(lk) free_lock(lk)
245
246static void
247acquire_lock(lk)
248 struct lockit *lk;
249{

--- 32 unchanged lines hidden (view full) ---

282{
283
284 if (lk.lkt_held != NOHOLDER)
285 FREE_LOCK(&lk);
286 panic(msg);
287}
288#endif /* DEBUG */
289
293static int interlocked_sleep __P((struct lockit *, int, void *, int,
294 const char *, int));
290static int interlocked_sleep(struct lockit *, int, void *, int,
291 const char *, int);
295
296/*
297 * When going to sleep, we must save our SPL so that it does
298 * not get lost if some other process uses the lock while we
299 * are sleeping. We restore it after we have slept. This routine
300 * wraps the interlocking with functions that sleep. The list
301 * below enumerates the available set of operations.
302 */

--- 50 unchanged lines hidden (view full) ---

353 */
354struct sema {
355 int value;
356 struct thread *holder;
357 char *name;
358 int prio;
359 int timo;
360};
292
293/*
294 * When going to sleep, we must save our SPL so that it does
295 * not get lost if some other process uses the lock while we
296 * are sleeping. We restore it after we have slept. This routine
297 * wraps the interlocking with functions that sleep. The list
298 * below enumerates the available set of operations.
299 */

--- 50 unchanged lines hidden (view full) ---

350 */
351struct sema {
352 int value;
353 struct thread *holder;
354 char *name;
355 int prio;
356 int timo;
357};
361static void sema_init __P((struct sema *, char *, int, int));
362static int sema_get __P((struct sema *, struct lockit *));
363static void sema_release __P((struct sema *));
358static void sema_init(struct sema *, char *, int, int);
359static int sema_get(struct sema *, struct lockit *);
360static void sema_release(struct sema *);
364
365static void
366sema_init(semap, name, prio, timo)
367 struct sema *semap;
368 char *name;
369 int prio, timo;
370{
371

--- 55 unchanged lines hidden (view full) ---

427} while (0)
428#define WORKLIST_REMOVE(item) do { \
429 (item)->wk_state &= ~ONWORKLIST; \
430 LIST_REMOVE(item, wk_list); \
431} while (0)
432#define WORKITEM_FREE(item, type) FREE(item, DtoM(type))
433
434#else /* DEBUG */
361
362static void
363sema_init(semap, name, prio, timo)
364 struct sema *semap;
365 char *name;
366 int prio, timo;
367{
368

--- 55 unchanged lines hidden (view full) ---

424} while (0)
425#define WORKLIST_REMOVE(item) do { \
426 (item)->wk_state &= ~ONWORKLIST; \
427 LIST_REMOVE(item, wk_list); \
428} while (0)
429#define WORKITEM_FREE(item, type) FREE(item, DtoM(type))
430
431#else /* DEBUG */
435static void worklist_insert __P((struct workhead *, struct worklist *));
436static void worklist_remove __P((struct worklist *));
437static void workitem_free __P((struct worklist *, int));
432static void worklist_insert(struct workhead *, struct worklist *);
433static void worklist_remove(struct worklist *);
434static void workitem_free(struct worklist *, int);
438
439#define WORKLIST_INSERT(head, item) worklist_insert(head, item)
440#define WORKLIST_REMOVE(item) worklist_remove(item)
441#define WORKITEM_FREE(item, type) workitem_free((struct worklist *)item, type)
442
443static void
444worklist_insert(head, item)
445 struct workhead *head;

--- 4839 unchanged lines hidden ---
435
436#define WORKLIST_INSERT(head, item) worklist_insert(head, item)
437#define WORKLIST_REMOVE(item) worklist_remove(item)
438#define WORKITEM_FREE(item, type) workitem_free((struct worklist *)item, type)
439
440static void
441worklist_insert(head, item)
442 struct workhead *head;

--- 4839 unchanged lines hidden ---