Commit cd4816fe authored by Nathan Scott's avatar Nathan Scott Committed by Stephen Lord

[XFS] Implement support for unwritten extents in XFS.

SGI Modid: 2.5.x-xfs:slinx:141508a
parent 1d1c803e
This diff is collapsed.
...@@ -66,5 +66,6 @@ extern struct file_operations linvfs_dir_operations; ...@@ -66,5 +66,6 @@ extern struct file_operations linvfs_dir_operations;
extern struct address_space_operations linvfs_aops; extern struct address_space_operations linvfs_aops;
extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int); extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern void linvfs_unwritten_done(struct buffer_head *, int);
#endif /* __XFS_IOPS_H__ */ #endif /* __XFS_IOPS_H__ */
...@@ -69,6 +69,20 @@ ...@@ -69,6 +69,20 @@
#define STATIC static #define STATIC static
#endif #endif
/*
* State flag for unwritten extent buffers.
*
* We need to be able to distinguish between these and delayed
* allocate buffers within XFS. The generic IO path code does
* not need to distinguish - we use the BH_Delay flag for both
* delalloc and these ondisk-uninitialised buffers.
*/
BUFFER_FNS(PrivateStart, unwritten);
static inline void set_buffer_unwritten_io(struct buffer_head *bh)
{
bh->b_end_io = linvfs_unwritten_done;
}
#define restricted_chown xfs_params.restrict_chown #define restricted_chown xfs_params.restrict_chown
#define irix_sgid_inherit xfs_params.sgid_inherit #define irix_sgid_inherit xfs_params.sgid_inherit
#define irix_symlink_mode xfs_params.symlink_mode #define irix_symlink_mode xfs_params.symlink_mode
......
...@@ -121,7 +121,8 @@ pb_trace_func( ...@@ -121,7 +121,8 @@ pb_trace_func(
STATIC kmem_cache_t *pagebuf_cache; STATIC kmem_cache_t *pagebuf_cache;
STATIC void pagebuf_daemon_wakeup(int); STATIC void pagebuf_daemon_wakeup(int);
STATIC void pagebuf_delwri_queue(page_buf_t *, int); STATIC void pagebuf_delwri_queue(page_buf_t *, int);
STATIC struct workqueue_struct *pagebuf_workqueue; STATIC struct workqueue_struct *pagebuf_logio_workqueue;
STATIC struct workqueue_struct *pagebuf_dataio_workqueue;
/* /*
* Pagebuf module configuration parameters, exported via * Pagebuf module configuration parameters, exported via
...@@ -785,6 +786,25 @@ pagebuf_get( /* allocate a buffer */ ...@@ -785,6 +786,25 @@ pagebuf_get( /* allocate a buffer */
return (pb); return (pb);
} }
/*
* Create a skeletal pagebuf (no pages associated with it).
*/
page_buf_t *
pagebuf_lookup(
struct pb_target *target,
loff_t ioff,
size_t isize,
page_buf_flags_t flags)
{
page_buf_t *pb;
pb = pagebuf_allocate(flags);
if (pb) {
_pagebuf_initialize(pb, target, ioff, isize, flags);
}
return pb;
}
/* /*
* If we are not low on memory then do the readahead in a deadlock * If we are not low on memory then do the readahead in a deadlock
* safe manner. * safe manner.
...@@ -1131,6 +1151,7 @@ pagebuf_iodone_work( ...@@ -1131,6 +1151,7 @@ pagebuf_iodone_work(
void void
pagebuf_iodone( pagebuf_iodone(
page_buf_t *pb, page_buf_t *pb,
int dataio,
int schedule) int schedule)
{ {
pb->pb_flags &= ~(PBF_READ | PBF_WRITE); pb->pb_flags &= ~(PBF_READ | PBF_WRITE);
...@@ -1143,7 +1164,8 @@ pagebuf_iodone( ...@@ -1143,7 +1164,8 @@ pagebuf_iodone(
if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) { if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) {
if (schedule) { if (schedule) {
INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb); INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb);
queue_work(pagebuf_workqueue, &pb->pb_iodone_work); queue_work(dataio ? pagebuf_dataio_workqueue :
pagebuf_logio_workqueue, &pb->pb_iodone_work);
} else { } else {
pagebuf_iodone_work(pb); pagebuf_iodone_work(pb);
} }
...@@ -1268,7 +1290,7 @@ bio_end_io_pagebuf( ...@@ -1268,7 +1290,7 @@ bio_end_io_pagebuf(
if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) {
pb->pb_locked = 0; pb->pb_locked = 0;
pagebuf_iodone(pb, 1); pagebuf_iodone(pb, 0, 1);
} }
bio_put(bio); bio_put(bio);
...@@ -1412,7 +1434,7 @@ pagebuf_iorequest( /* start real I/O */ ...@@ -1412,7 +1434,7 @@ pagebuf_iorequest( /* start real I/O */
if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) {
pb->pb_locked = 0; pb->pb_locked = 0;
pagebuf_iodone(pb, 0); pagebuf_iodone(pb, 0, 0);
} }
return 0; return 0;
...@@ -1734,13 +1756,21 @@ pagebuf_daemon_start(void) ...@@ -1734,13 +1756,21 @@ pagebuf_daemon_start(void)
{ {
int rval; int rval;
pagebuf_workqueue = create_workqueue("pagebuf"); pagebuf_logio_workqueue = create_workqueue("xfslogd");
if (!pagebuf_workqueue) if (!pagebuf_logio_workqueue)
return -ENOMEM; return -ENOMEM;
pagebuf_dataio_workqueue = create_workqueue("xfsdatad");
if (!pagebuf_dataio_workqueue) {
destroy_workqueue(pagebuf_logio_workqueue);
return -ENOMEM;
}
rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES); rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES);
if (rval < 0) if (rval < 0) {
destroy_workqueue(pagebuf_workqueue); destroy_workqueue(pagebuf_logio_workqueue);
destroy_workqueue(pagebuf_dataio_workqueue);
}
return rval; return rval;
} }
...@@ -1756,7 +1786,8 @@ pagebuf_daemon_stop(void) ...@@ -1756,7 +1786,8 @@ pagebuf_daemon_stop(void)
pbd_active = 0; pbd_active = 0;
wake_up_interruptible(&pbd_waitq); wake_up_interruptible(&pbd_waitq);
wait_event_interruptible(pbd_waitq, pbd_active); wait_event_interruptible(pbd_waitq, pbd_active);
destroy_workqueue(pagebuf_workqueue); destroy_workqueue(pagebuf_logio_workqueue);
destroy_workqueue(pagebuf_dataio_workqueue);
} }
......
...@@ -169,8 +169,8 @@ typedef page_buf_bmap_t pb_bmap_t; ...@@ -169,8 +169,8 @@ typedef page_buf_bmap_t pb_bmap_t;
* This buffer structure is used by the page cache buffer management routines * This buffer structure is used by the page cache buffer management routines
* to refer to an assembly of pages forming a logical buffer. The actual * to refer to an assembly of pages forming a logical buffer. The actual
* I/O is performed with buffer_head or bio structures, as required by drivers, * I/O is performed with buffer_head or bio structures, as required by drivers,
* for drivers which do not understand this structure. The buffer structure is * for drivers which do not understand this structure. The buffer structure is
* used on temporary basis only, and discarded when released. * used on temporary basis only, and discarded when released.
* *
* The real data storage is recorded in the page cache. Metadata is * The real data storage is recorded in the page cache. Metadata is
* hashed to the inode for the block device on which the file system resides. * hashed to the inode for the block device on which the file system resides.
...@@ -245,6 +245,13 @@ extern page_buf_t *pagebuf_get( /* allocate a buffer */ ...@@ -245,6 +245,13 @@ extern page_buf_t *pagebuf_get( /* allocate a buffer */
page_buf_flags_t); /* PBF_LOCK, PBF_READ, */ page_buf_flags_t); /* PBF_LOCK, PBF_READ, */
/* PBF_ASYNC */ /* PBF_ASYNC */
extern page_buf_t *pagebuf_lookup(
struct pb_target *,
loff_t, /* starting offset of range */
size_t, /* length of range */
page_buf_flags_t); /* PBF_READ, PBF_WRITE, */
/* PBF_FORCEIO, _PBF_LOCKABLE */
extern page_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */ extern page_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */
/* no memory or disk address */ /* no memory or disk address */
struct pb_target *); /* mount point "fake" inode */ struct pb_target *); /* mount point "fake" inode */
...@@ -300,6 +307,7 @@ static inline int pagebuf_geterror(page_buf_t *pb) ...@@ -300,6 +307,7 @@ static inline int pagebuf_geterror(page_buf_t *pb)
extern void pagebuf_iodone( /* mark buffer I/O complete */ extern void pagebuf_iodone( /* mark buffer I/O complete */
page_buf_t *, /* buffer to mark */ page_buf_t *, /* buffer to mark */
int, /* use data/log helper thread. */
int); /* run completion locally, or in int); /* run completion locally, or in
* a helper thread. */ * a helper thread. */
......
...@@ -163,15 +163,17 @@ extern inline xfs_caddr_t xfs_buf_offset(page_buf_t *bp, size_t offset) ...@@ -163,15 +163,17 @@ extern inline xfs_caddr_t xfs_buf_offset(page_buf_t *bp, size_t offset)
#define XFS_BUF_SET_PTR(bp, val, count) \ #define XFS_BUF_SET_PTR(bp, val, count) \
pagebuf_associate_memory(bp, val, count) pagebuf_associate_memory(bp, val, count)
#define XFS_BUF_ADDR(bp) ((bp)->pb_bn) #define XFS_BUF_ADDR(bp) ((bp)->pb_bn)
#define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset >> 9)
#define XFS_BUF_SET_ADDR(bp, blk) \ #define XFS_BUF_SET_ADDR(bp, blk) \
((bp)->pb_bn = (page_buf_daddr_t)(blk)) ((bp)->pb_bn = (page_buf_daddr_t)(blk))
#define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset)
#define XFS_BUF_SET_OFFSET(bp, off) \
((bp)->pb_file_offset = (off))
#define XFS_BUF_COUNT(bp) ((bp)->pb_count_desired) #define XFS_BUF_COUNT(bp) ((bp)->pb_count_desired)
#define XFS_BUF_SET_COUNT(bp, cnt) \ #define XFS_BUF_SET_COUNT(bp, cnt) \
((bp)->pb_count_desired = cnt) ((bp)->pb_count_desired = (cnt))
#define XFS_BUF_SIZE(bp) ((bp)->pb_buffer_length) #define XFS_BUF_SIZE(bp) ((bp)->pb_buffer_length)
#define XFS_BUF_SET_SIZE(bp, cnt) \ #define XFS_BUF_SET_SIZE(bp, cnt) \
((bp)->pb_buffer_length = cnt) ((bp)->pb_buffer_length = (cnt))
#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) #define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
#define XFS_BUF_SET_VTYPE(bp, type) #define XFS_BUF_SET_VTYPE(bp, type)
#define XFS_BUF_SET_REF(bp, ref) #define XFS_BUF_SET_REF(bp, ref)
...@@ -242,7 +244,7 @@ static inline void xfs_buf_relse(page_buf_t *bp) ...@@ -242,7 +244,7 @@ static inline void xfs_buf_relse(page_buf_t *bp)
#define xfs_biodone(pb) \ #define xfs_biodone(pb) \
pagebuf_iodone(pb, 0) pagebuf_iodone(pb, 0, 0)
#define xfs_incore(buftarg,blkno,len,lockit) \ #define xfs_incore(buftarg,blkno,len,lockit) \
pagebuf_find(buftarg, blkno ,len, lockit) pagebuf_find(buftarg, blkno ,len, lockit)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment