diff options
Diffstat (limited to 'fs/xfs/linux-2.6')
30 files changed, 2466 insertions, 1621 deletions
diff --git a/fs/xfs/linux-2.6/sv.h b/fs/xfs/linux-2.6/sv.h index 351a8f454bd1..4dfc7c370819 100644 --- a/fs/xfs/linux-2.6/sv.h +++ b/fs/xfs/linux-2.6/sv.h | |||
@@ -32,23 +32,15 @@ typedef struct sv_s { | |||
32 | wait_queue_head_t waiters; | 32 | wait_queue_head_t waiters; |
33 | } sv_t; | 33 | } sv_t; |
34 | 34 | ||
35 | #define SV_FIFO 0x0 /* sv_t is FIFO type */ | 35 | static inline void _sv_wait(sv_t *sv, spinlock_t *lock) |
36 | #define SV_LIFO 0x2 /* sv_t is LIFO type */ | ||
37 | #define SV_PRIO 0x4 /* sv_t is PRIO type */ | ||
38 | #define SV_KEYED 0x6 /* sv_t is KEYED type */ | ||
39 | #define SV_DEFAULT SV_FIFO | ||
40 | |||
41 | |||
42 | static inline void _sv_wait(sv_t *sv, spinlock_t *lock, int state, | ||
43 | unsigned long timeout) | ||
44 | { | 36 | { |
45 | DECLARE_WAITQUEUE(wait, current); | 37 | DECLARE_WAITQUEUE(wait, current); |
46 | 38 | ||
47 | add_wait_queue_exclusive(&sv->waiters, &wait); | 39 | add_wait_queue_exclusive(&sv->waiters, &wait); |
48 | __set_current_state(state); | 40 | __set_current_state(TASK_UNINTERRUPTIBLE); |
49 | spin_unlock(lock); | 41 | spin_unlock(lock); |
50 | 42 | ||
51 | schedule_timeout(timeout); | 43 | schedule(); |
52 | 44 | ||
53 | remove_wait_queue(&sv->waiters, &wait); | 45 | remove_wait_queue(&sv->waiters, &wait); |
54 | } | 46 | } |
@@ -58,13 +50,7 @@ static inline void _sv_wait(sv_t *sv, spinlock_t *lock, int state, | |||
58 | #define sv_destroy(sv) \ | 50 | #define sv_destroy(sv) \ |
59 | /*NOTHING*/ | 51 | /*NOTHING*/ |
60 | #define sv_wait(sv, pri, lock, s) \ | 52 | #define sv_wait(sv, pri, lock, s) \ |
61 | _sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT) | 53 | _sv_wait(sv, lock) |
62 | #define sv_wait_sig(sv, pri, lock, s) \ | ||
63 | _sv_wait(sv, lock, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT) | ||
64 | #define sv_timedwait(sv, pri, lock, s, svf, ts, rts) \ | ||
65 | _sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, timespec_to_jiffies(ts)) | ||
66 | #define sv_timedwait_sig(sv, pri, lock, s, svf, ts, rts) \ | ||
67 | _sv_wait(sv, lock, TASK_INTERRUPTIBLE, timespec_to_jiffies(ts)) | ||
68 | #define sv_signal(sv) \ | 54 | #define sv_signal(sv) \ |
69 | wake_up(&(sv)->waiters) | 55 | wake_up(&(sv)->waiters) |
70 | #define sv_broadcast(sv) \ | 56 | #define sv_broadcast(sv) \ |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index a44d68eb50b5..de3a198f771e 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -42,6 +42,40 @@ | |||
42 | #include <linux/pagevec.h> | 42 | #include <linux/pagevec.h> |
43 | #include <linux/writeback.h> | 43 | #include <linux/writeback.h> |
44 | 44 | ||
45 | |||
46 | /* | ||
47 | * Prime number of hash buckets since address is used as the key. | ||
48 | */ | ||
49 | #define NVSYNC 37 | ||
50 | #define to_ioend_wq(v) (&xfs_ioend_wq[((unsigned long)v) % NVSYNC]) | ||
51 | static wait_queue_head_t xfs_ioend_wq[NVSYNC]; | ||
52 | |||
53 | void __init | ||
54 | xfs_ioend_init(void) | ||
55 | { | ||
56 | int i; | ||
57 | |||
58 | for (i = 0; i < NVSYNC; i++) | ||
59 | init_waitqueue_head(&xfs_ioend_wq[i]); | ||
60 | } | ||
61 | |||
62 | void | ||
63 | xfs_ioend_wait( | ||
64 | xfs_inode_t *ip) | ||
65 | { | ||
66 | wait_queue_head_t *wq = to_ioend_wq(ip); | ||
67 | |||
68 | wait_event(*wq, (atomic_read(&ip->i_iocount) == 0)); | ||
69 | } | ||
70 | |||
71 | STATIC void | ||
72 | xfs_ioend_wake( | ||
73 | xfs_inode_t *ip) | ||
74 | { | ||
75 | if (atomic_dec_and_test(&ip->i_iocount)) | ||
76 | wake_up(to_ioend_wq(ip)); | ||
77 | } | ||
78 | |||
45 | STATIC void | 79 | STATIC void |
46 | xfs_count_page_state( | 80 | xfs_count_page_state( |
47 | struct page *page, | 81 | struct page *page, |
@@ -146,16 +180,25 @@ xfs_destroy_ioend( | |||
146 | xfs_ioend_t *ioend) | 180 | xfs_ioend_t *ioend) |
147 | { | 181 | { |
148 | struct buffer_head *bh, *next; | 182 | struct buffer_head *bh, *next; |
183 | struct xfs_inode *ip = XFS_I(ioend->io_inode); | ||
149 | 184 | ||
150 | for (bh = ioend->io_buffer_head; bh; bh = next) { | 185 | for (bh = ioend->io_buffer_head; bh; bh = next) { |
151 | next = bh->b_private; | 186 | next = bh->b_private; |
152 | bh->b_end_io(bh, !ioend->io_error); | 187 | bh->b_end_io(bh, !ioend->io_error); |
153 | } | 188 | } |
154 | if (unlikely(ioend->io_error)) { | 189 | |
155 | vn_ioerror(XFS_I(ioend->io_inode), ioend->io_error, | 190 | /* |
156 | __FILE__,__LINE__); | 191 | * Volume managers supporting multiple paths can send back ENODEV |
192 | * when the final path disappears. In this case continuing to fill | ||
193 | * the page cache with dirty data which cannot be written out is | ||
194 | * evil, so prevent that. | ||
195 | */ | ||
196 | if (unlikely(ioend->io_error == -ENODEV)) { | ||
197 | xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, | ||
198 | __FILE__, __LINE__); | ||
157 | } | 199 | } |
158 | vn_iowake(XFS_I(ioend->io_inode)); | 200 | |
201 | xfs_ioend_wake(ip); | ||
159 | mempool_free(ioend, xfs_ioend_pool); | 202 | mempool_free(ioend, xfs_ioend_pool); |
160 | } | 203 | } |
161 | 204 | ||
@@ -191,7 +234,7 @@ xfs_setfilesize( | |||
191 | ip->i_d.di_size = isize; | 234 | ip->i_d.di_size = isize; |
192 | ip->i_update_core = 1; | 235 | ip->i_update_core = 1; |
193 | ip->i_update_size = 1; | 236 | ip->i_update_size = 1; |
194 | mark_inode_dirty_sync(ioend->io_inode); | 237 | xfs_mark_inode_dirty_sync(ip); |
195 | } | 238 | } |
196 | 239 | ||
197 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 240 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
@@ -317,14 +360,9 @@ xfs_map_blocks( | |||
317 | xfs_iomap_t *mapp, | 360 | xfs_iomap_t *mapp, |
318 | int flags) | 361 | int flags) |
319 | { | 362 | { |
320 | xfs_inode_t *ip = XFS_I(inode); | 363 | int nmaps = 1; |
321 | int error, nmaps = 1; | 364 | |
322 | 365 | return -xfs_iomap(XFS_I(inode), offset, count, flags, mapp, &nmaps); | |
323 | error = xfs_iomap(ip, offset, count, | ||
324 | flags, mapp, &nmaps); | ||
325 | if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE))) | ||
326 | xfs_iflags_set(ip, XFS_IMODIFIED); | ||
327 | return -error; | ||
328 | } | 366 | } |
329 | 367 | ||
330 | STATIC_INLINE int | 368 | STATIC_INLINE int |
@@ -512,7 +550,7 @@ xfs_cancel_ioend( | |||
512 | unlock_buffer(bh); | 550 | unlock_buffer(bh); |
513 | } while ((bh = next_bh) != NULL); | 551 | } while ((bh = next_bh) != NULL); |
514 | 552 | ||
515 | vn_iowake(XFS_I(ioend->io_inode)); | 553 | xfs_ioend_wake(XFS_I(ioend->io_inode)); |
516 | mempool_free(ioend, xfs_ioend_pool); | 554 | mempool_free(ioend, xfs_ioend_pool); |
517 | } while ((ioend = next) != NULL); | 555 | } while ((ioend = next) != NULL); |
518 | } | 556 | } |
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 3ba0631a3818..7b26f5ff9692 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h | |||
@@ -43,4 +43,7 @@ typedef struct xfs_ioend { | |||
43 | extern const struct address_space_operations xfs_address_space_operations; | 43 | extern const struct address_space_operations xfs_address_space_operations; |
44 | extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); | 44 | extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); |
45 | 45 | ||
46 | extern void xfs_ioend_init(void); | ||
47 | extern void xfs_ioend_wait(struct xfs_inode *); | ||
48 | |||
46 | #endif /* __XFS_AOPS_H__ */ | 49 | #endif /* __XFS_AOPS_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 36d5fcd3f593..cb329edc925b 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -630,6 +630,29 @@ xfs_buf_get_flags( | |||
630 | return NULL; | 630 | return NULL; |
631 | } | 631 | } |
632 | 632 | ||
633 | STATIC int | ||
634 | _xfs_buf_read( | ||
635 | xfs_buf_t *bp, | ||
636 | xfs_buf_flags_t flags) | ||
637 | { | ||
638 | int status; | ||
639 | |||
640 | XB_TRACE(bp, "_xfs_buf_read", (unsigned long)flags); | ||
641 | |||
642 | ASSERT(!(flags & (XBF_DELWRI|XBF_WRITE))); | ||
643 | ASSERT(bp->b_bn != XFS_BUF_DADDR_NULL); | ||
644 | |||
645 | bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_DELWRI | \ | ||
646 | XBF_READ_AHEAD | _XBF_RUN_QUEUES); | ||
647 | bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | \ | ||
648 | XBF_READ_AHEAD | _XBF_RUN_QUEUES); | ||
649 | |||
650 | status = xfs_buf_iorequest(bp); | ||
651 | if (!status && !(flags & XBF_ASYNC)) | ||
652 | status = xfs_buf_iowait(bp); | ||
653 | return status; | ||
654 | } | ||
655 | |||
633 | xfs_buf_t * | 656 | xfs_buf_t * |
634 | xfs_buf_read_flags( | 657 | xfs_buf_read_flags( |
635 | xfs_buftarg_t *target, | 658 | xfs_buftarg_t *target, |
@@ -646,7 +669,7 @@ xfs_buf_read_flags( | |||
646 | if (!XFS_BUF_ISDONE(bp)) { | 669 | if (!XFS_BUF_ISDONE(bp)) { |
647 | XB_TRACE(bp, "read", (unsigned long)flags); | 670 | XB_TRACE(bp, "read", (unsigned long)flags); |
648 | XFS_STATS_INC(xb_get_read); | 671 | XFS_STATS_INC(xb_get_read); |
649 | xfs_buf_iostart(bp, flags); | 672 | _xfs_buf_read(bp, flags); |
650 | } else if (flags & XBF_ASYNC) { | 673 | } else if (flags & XBF_ASYNC) { |
651 | XB_TRACE(bp, "read_async", (unsigned long)flags); | 674 | XB_TRACE(bp, "read_async", (unsigned long)flags); |
652 | /* | 675 | /* |
@@ -1048,50 +1071,39 @@ xfs_buf_ioerror( | |||
1048 | XB_TRACE(bp, "ioerror", (unsigned long)error); | 1071 | XB_TRACE(bp, "ioerror", (unsigned long)error); |
1049 | } | 1072 | } |
1050 | 1073 | ||
1051 | /* | ||
1052 | * Initiate I/O on a buffer, based on the flags supplied. | ||
1053 | * The b_iodone routine in the buffer supplied will only be called | ||
1054 | * when all of the subsidiary I/O requests, if any, have been completed. | ||
1055 | */ | ||
1056 | int | 1074 | int |
1057 | xfs_buf_iostart( | 1075 | xfs_bawrite( |
1058 | xfs_buf_t *bp, | 1076 | void *mp, |
1059 | xfs_buf_flags_t flags) | 1077 | struct xfs_buf *bp) |
1060 | { | 1078 | { |
1061 | int status = 0; | 1079 | XB_TRACE(bp, "bawrite", 0); |
1062 | 1080 | ||
1063 | XB_TRACE(bp, "iostart", (unsigned long)flags); | 1081 | ASSERT(bp->b_bn != XFS_BUF_DADDR_NULL); |
1064 | 1082 | ||
1065 | if (flags & XBF_DELWRI) { | 1083 | xfs_buf_delwri_dequeue(bp); |
1066 | bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC); | ||
1067 | bp->b_flags |= flags & (XBF_DELWRI | XBF_ASYNC); | ||
1068 | xfs_buf_delwri_queue(bp, 1); | ||
1069 | return 0; | ||
1070 | } | ||
1071 | 1084 | ||
1072 | bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC | XBF_DELWRI | \ | 1085 | bp->b_flags &= ~(XBF_READ | XBF_DELWRI | XBF_READ_AHEAD); |
1073 | XBF_READ_AHEAD | _XBF_RUN_QUEUES); | 1086 | bp->b_flags |= (XBF_WRITE | XBF_ASYNC | _XBF_RUN_QUEUES); |
1074 | bp->b_flags |= flags & (XBF_READ | XBF_WRITE | XBF_ASYNC | \ | 1087 | |
1075 | XBF_READ_AHEAD | _XBF_RUN_QUEUES); | 1088 | bp->b_mount = mp; |
1089 | bp->b_strat = xfs_bdstrat_cb; | ||
1090 | return xfs_bdstrat_cb(bp); | ||
1091 | } | ||
1076 | 1092 | ||
1077 | BUG_ON(bp->b_bn == XFS_BUF_DADDR_NULL); | 1093 | void |
1094 | xfs_bdwrite( | ||
1095 | void *mp, | ||
1096 | struct xfs_buf *bp) | ||
1097 | { | ||
1098 | XB_TRACE(bp, "bdwrite", 0); | ||
1078 | 1099 | ||
1079 | /* For writes allow an alternate strategy routine to precede | 1100 | bp->b_strat = xfs_bdstrat_cb; |
1080 | * the actual I/O request (which may not be issued at all in | 1101 | bp->b_mount = mp; |
1081 | * a shutdown situation, for example). | ||
1082 | */ | ||
1083 | status = (flags & XBF_WRITE) ? | ||
1084 | xfs_buf_iostrategy(bp) : xfs_buf_iorequest(bp); | ||
1085 | 1102 | ||
1086 | /* Wait for I/O if we are not an async request. | 1103 | bp->b_flags &= ~XBF_READ; |
1087 | * Note: async I/O request completion will release the buffer, | 1104 | bp->b_flags |= (XBF_DELWRI | XBF_ASYNC); |
1088 | * and that can already be done by this point. So using the | ||
1089 | * buffer pointer from here on, after async I/O, is invalid. | ||
1090 | */ | ||
1091 | if (!status && !(flags & XBF_ASYNC)) | ||
1092 | status = xfs_buf_iowait(bp); | ||
1093 | 1105 | ||
1094 | return status; | 1106 | xfs_buf_delwri_queue(bp, 1); |
1095 | } | 1107 | } |
1096 | 1108 | ||
1097 | STATIC_INLINE void | 1109 | STATIC_INLINE void |
@@ -1114,8 +1126,7 @@ xfs_buf_bio_end_io( | |||
1114 | unsigned int blocksize = bp->b_target->bt_bsize; | 1126 | unsigned int blocksize = bp->b_target->bt_bsize; |
1115 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 1127 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; |
1116 | 1128 | ||
1117 | if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) | 1129 | xfs_buf_ioerror(bp, -error); |
1118 | bp->b_error = EIO; | ||
1119 | 1130 | ||
1120 | do { | 1131 | do { |
1121 | struct page *page = bvec->bv_page; | 1132 | struct page *page = bvec->bv_page; |
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index 456519a088c7..288ae7c4c800 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h | |||
@@ -168,7 +168,7 @@ typedef struct xfs_buf { | |||
168 | struct completion b_iowait; /* queue for I/O waiters */ | 168 | struct completion b_iowait; /* queue for I/O waiters */ |
169 | void *b_fspriv; | 169 | void *b_fspriv; |
170 | void *b_fspriv2; | 170 | void *b_fspriv2; |
171 | void *b_fspriv3; | 171 | struct xfs_mount *b_mount; |
172 | unsigned short b_error; /* error code on I/O */ | 172 | unsigned short b_error; /* error code on I/O */ |
173 | unsigned int b_page_count; /* size of page array */ | 173 | unsigned int b_page_count; /* size of page array */ |
174 | unsigned int b_offset; /* page offset in first page */ | 174 | unsigned int b_offset; /* page offset in first page */ |
@@ -214,9 +214,10 @@ extern void xfs_buf_lock(xfs_buf_t *); | |||
214 | extern void xfs_buf_unlock(xfs_buf_t *); | 214 | extern void xfs_buf_unlock(xfs_buf_t *); |
215 | 215 | ||
216 | /* Buffer Read and Write Routines */ | 216 | /* Buffer Read and Write Routines */ |
217 | extern int xfs_bawrite(void *mp, xfs_buf_t *bp); | ||
218 | extern void xfs_bdwrite(void *mp, xfs_buf_t *bp); | ||
217 | extern void xfs_buf_ioend(xfs_buf_t *, int); | 219 | extern void xfs_buf_ioend(xfs_buf_t *, int); |
218 | extern void xfs_buf_ioerror(xfs_buf_t *, int); | 220 | extern void xfs_buf_ioerror(xfs_buf_t *, int); |
219 | extern int xfs_buf_iostart(xfs_buf_t *, xfs_buf_flags_t); | ||
220 | extern int xfs_buf_iorequest(xfs_buf_t *); | 221 | extern int xfs_buf_iorequest(xfs_buf_t *); |
221 | extern int xfs_buf_iowait(xfs_buf_t *); | 222 | extern int xfs_buf_iowait(xfs_buf_t *); |
222 | extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, xfs_caddr_t, | 223 | extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, xfs_caddr_t, |
@@ -311,10 +312,6 @@ extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *); | |||
311 | #define XFS_BUF_UNORDERED(bp) ((bp)->b_flags &= ~XBF_ORDERED) | 312 | #define XFS_BUF_UNORDERED(bp) ((bp)->b_flags &= ~XBF_ORDERED) |
312 | #define XFS_BUF_ISORDERED(bp) ((bp)->b_flags & XBF_ORDERED) | 313 | #define XFS_BUF_ISORDERED(bp) ((bp)->b_flags & XBF_ORDERED) |
313 | 314 | ||
314 | #define XFS_BUF_SHUT(bp) do { } while (0) | ||
315 | #define XFS_BUF_UNSHUT(bp) do { } while (0) | ||
316 | #define XFS_BUF_ISSHUT(bp) (0) | ||
317 | |||
318 | #define XFS_BUF_HOLD(bp) xfs_buf_hold(bp) | 315 | #define XFS_BUF_HOLD(bp) xfs_buf_hold(bp) |
319 | #define XFS_BUF_READ(bp) ((bp)->b_flags |= XBF_READ) | 316 | #define XFS_BUF_READ(bp) ((bp)->b_flags |= XBF_READ) |
320 | #define XFS_BUF_UNREAD(bp) ((bp)->b_flags &= ~XBF_READ) | 317 | #define XFS_BUF_UNREAD(bp) ((bp)->b_flags &= ~XBF_READ) |
@@ -334,8 +331,6 @@ extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *); | |||
334 | #define XFS_BUF_SET_FSPRIVATE(bp, val) ((bp)->b_fspriv = (void*)(val)) | 331 | #define XFS_BUF_SET_FSPRIVATE(bp, val) ((bp)->b_fspriv = (void*)(val)) |
335 | #define XFS_BUF_FSPRIVATE2(bp, type) ((type)(bp)->b_fspriv2) | 332 | #define XFS_BUF_FSPRIVATE2(bp, type) ((type)(bp)->b_fspriv2) |
336 | #define XFS_BUF_SET_FSPRIVATE2(bp, val) ((bp)->b_fspriv2 = (void*)(val)) | 333 | #define XFS_BUF_SET_FSPRIVATE2(bp, val) ((bp)->b_fspriv2 = (void*)(val)) |
337 | #define XFS_BUF_FSPRIVATE3(bp, type) ((type)(bp)->b_fspriv3) | ||
338 | #define XFS_BUF_SET_FSPRIVATE3(bp, val) ((bp)->b_fspriv3 = (void*)(val)) | ||
339 | #define XFS_BUF_SET_START(bp) do { } while (0) | 334 | #define XFS_BUF_SET_START(bp) do { } while (0) |
340 | #define XFS_BUF_SET_BRELSE_FUNC(bp, func) ((bp)->b_relse = (func)) | 335 | #define XFS_BUF_SET_BRELSE_FUNC(bp, func) ((bp)->b_relse = (func)) |
341 | 336 | ||
@@ -366,14 +361,6 @@ extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *); | |||
366 | #define XFS_BUF_TARGET(bp) ((bp)->b_target) | 361 | #define XFS_BUF_TARGET(bp) ((bp)->b_target) |
367 | #define XFS_BUFTARG_NAME(target) xfs_buf_target_name(target) | 362 | #define XFS_BUFTARG_NAME(target) xfs_buf_target_name(target) |
368 | 363 | ||
369 | static inline int xfs_bawrite(void *mp, xfs_buf_t *bp) | ||
370 | { | ||
371 | bp->b_fspriv3 = mp; | ||
372 | bp->b_strat = xfs_bdstrat_cb; | ||
373 | xfs_buf_delwri_dequeue(bp); | ||
374 | return xfs_buf_iostart(bp, XBF_WRITE | XBF_ASYNC | _XBF_RUN_QUEUES); | ||
375 | } | ||
376 | |||
377 | static inline void xfs_buf_relse(xfs_buf_t *bp) | 364 | static inline void xfs_buf_relse(xfs_buf_t *bp) |
378 | { | 365 | { |
379 | if (!bp->b_relse) | 366 | if (!bp->b_relse) |
@@ -414,17 +401,6 @@ static inline int XFS_bwrite(xfs_buf_t *bp) | |||
414 | return error; | 401 | return error; |
415 | } | 402 | } |
416 | 403 | ||
417 | /* | ||
418 | * No error can be returned from xfs_buf_iostart for delwri | ||
419 | * buffers as they are queued and no I/O is issued. | ||
420 | */ | ||
421 | static inline void xfs_bdwrite(void *mp, xfs_buf_t *bp) | ||
422 | { | ||
423 | bp->b_strat = xfs_bdstrat_cb; | ||
424 | bp->b_fspriv3 = mp; | ||
425 | (void)xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC); | ||
426 | } | ||
427 | |||
428 | #define XFS_bdstrat(bp) xfs_buf_iorequest(bp) | 404 | #define XFS_bdstrat(bp) xfs_buf_iorequest(bp) |
429 | 405 | ||
430 | #define xfs_iowait(bp) xfs_buf_iowait(bp) | 406 | #define xfs_iowait(bp) xfs_buf_iowait(bp) |
diff --git a/fs/xfs/linux-2.6/xfs_cred.h b/fs/xfs/linux-2.6/xfs_cred.h index 8c022cd0ad67..55bddf3b6091 100644 --- a/fs/xfs/linux-2.6/xfs_cred.h +++ b/fs/xfs/linux-2.6/xfs_cred.h | |||
@@ -25,12 +25,4 @@ | |||
25 | */ | 25 | */ |
26 | typedef const struct cred cred_t; | 26 | typedef const struct cred cred_t; |
27 | 27 | ||
28 | extern cred_t *sys_cred; | ||
29 | |||
30 | /* this is a hack.. (assumes sys_cred is the only cred_t in the system) */ | ||
31 | static inline int capable_cred(cred_t *cr, int cid) | ||
32 | { | ||
33 | return (cr == sys_cred) ? 1 : capable(cid); | ||
34 | } | ||
35 | |||
36 | #endif /* __XFS_CRED_H__ */ | 28 | #endif /* __XFS_CRED_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index 7f7abec25e14..595751f78350 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include "xfs_vnodeops.h" | 29 | #include "xfs_vnodeops.h" |
30 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_inode.h" | 31 | #include "xfs_inode.h" |
32 | #include "xfs_vfsops.h" | ||
33 | 32 | ||
34 | /* | 33 | /* |
35 | * Note that we only accept fileids which are long enough rather than allow | 34 | * Note that we only accept fileids which are long enough rather than allow |
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 3fee790f138b..e14c4e3aea0c 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -36,89 +36,54 @@ | |||
36 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
37 | #include "xfs_error.h" | 37 | #include "xfs_error.h" |
38 | #include "xfs_rw.h" | 38 | #include "xfs_rw.h" |
39 | #include "xfs_ioctl32.h" | ||
40 | #include "xfs_vnodeops.h" | 39 | #include "xfs_vnodeops.h" |
40 | #include "xfs_da_btree.h" | ||
41 | #include "xfs_ioctl.h" | ||
41 | 42 | ||
42 | #include <linux/dcache.h> | 43 | #include <linux/dcache.h> |
43 | #include <linux/smp_lock.h> | 44 | #include <linux/smp_lock.h> |
44 | 45 | ||
45 | static struct vm_operations_struct xfs_file_vm_ops; | 46 | static struct vm_operations_struct xfs_file_vm_ops; |
46 | 47 | ||
47 | STATIC_INLINE ssize_t | 48 | STATIC ssize_t |
48 | __xfs_file_read( | 49 | xfs_file_aio_read( |
49 | struct kiocb *iocb, | 50 | struct kiocb *iocb, |
50 | const struct iovec *iov, | 51 | const struct iovec *iov, |
51 | unsigned long nr_segs, | 52 | unsigned long nr_segs, |
52 | int ioflags, | ||
53 | loff_t pos) | 53 | loff_t pos) |
54 | { | 54 | { |
55 | struct file *file = iocb->ki_filp; | 55 | struct file *file = iocb->ki_filp; |
56 | int ioflags = IO_ISAIO; | ||
56 | 57 | ||
57 | BUG_ON(iocb->ki_pos != pos); | 58 | BUG_ON(iocb->ki_pos != pos); |
58 | if (unlikely(file->f_flags & O_DIRECT)) | 59 | if (unlikely(file->f_flags & O_DIRECT)) |
59 | ioflags |= IO_ISDIRECT; | 60 | ioflags |= IO_ISDIRECT; |
61 | if (file->f_mode & FMODE_NOCMTIME) | ||
62 | ioflags |= IO_INVIS; | ||
60 | return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov, | 63 | return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov, |
61 | nr_segs, &iocb->ki_pos, ioflags); | 64 | nr_segs, &iocb->ki_pos, ioflags); |
62 | } | 65 | } |
63 | 66 | ||
64 | STATIC ssize_t | 67 | STATIC ssize_t |
65 | xfs_file_aio_read( | 68 | xfs_file_aio_write( |
66 | struct kiocb *iocb, | ||
67 | const struct iovec *iov, | ||
68 | unsigned long nr_segs, | ||
69 | loff_t pos) | ||
70 | { | ||
71 | return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO, pos); | ||
72 | } | ||
73 | |||
74 | STATIC ssize_t | ||
75 | xfs_file_aio_read_invis( | ||
76 | struct kiocb *iocb, | ||
77 | const struct iovec *iov, | ||
78 | unsigned long nr_segs, | ||
79 | loff_t pos) | ||
80 | { | ||
81 | return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos); | ||
82 | } | ||
83 | |||
84 | STATIC_INLINE ssize_t | ||
85 | __xfs_file_write( | ||
86 | struct kiocb *iocb, | 69 | struct kiocb *iocb, |
87 | const struct iovec *iov, | 70 | const struct iovec *iov, |
88 | unsigned long nr_segs, | 71 | unsigned long nr_segs, |
89 | int ioflags, | ||
90 | loff_t pos) | 72 | loff_t pos) |
91 | { | 73 | { |
92 | struct file *file = iocb->ki_filp; | 74 | struct file *file = iocb->ki_filp; |
75 | int ioflags = IO_ISAIO; | ||
93 | 76 | ||
94 | BUG_ON(iocb->ki_pos != pos); | 77 | BUG_ON(iocb->ki_pos != pos); |
95 | if (unlikely(file->f_flags & O_DIRECT)) | 78 | if (unlikely(file->f_flags & O_DIRECT)) |
96 | ioflags |= IO_ISDIRECT; | 79 | ioflags |= IO_ISDIRECT; |
80 | if (file->f_mode & FMODE_NOCMTIME) | ||
81 | ioflags |= IO_INVIS; | ||
97 | return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs, | 82 | return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs, |
98 | &iocb->ki_pos, ioflags); | 83 | &iocb->ki_pos, ioflags); |
99 | } | 84 | } |
100 | 85 | ||
101 | STATIC ssize_t | 86 | STATIC ssize_t |
102 | xfs_file_aio_write( | ||
103 | struct kiocb *iocb, | ||
104 | const struct iovec *iov, | ||
105 | unsigned long nr_segs, | ||
106 | loff_t pos) | ||
107 | { | ||
108 | return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO, pos); | ||
109 | } | ||
110 | |||
111 | STATIC ssize_t | ||
112 | xfs_file_aio_write_invis( | ||
113 | struct kiocb *iocb, | ||
114 | const struct iovec *iov, | ||
115 | unsigned long nr_segs, | ||
116 | loff_t pos) | ||
117 | { | ||
118 | return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos); | ||
119 | } | ||
120 | |||
121 | STATIC ssize_t | ||
122 | xfs_file_splice_read( | 87 | xfs_file_splice_read( |
123 | struct file *infilp, | 88 | struct file *infilp, |
124 | loff_t *ppos, | 89 | loff_t *ppos, |
@@ -126,20 +91,13 @@ xfs_file_splice_read( | |||
126 | size_t len, | 91 | size_t len, |
127 | unsigned int flags) | 92 | unsigned int flags) |
128 | { | 93 | { |
129 | return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode), | 94 | int ioflags = 0; |
130 | infilp, ppos, pipe, len, flags, 0); | 95 | |
131 | } | 96 | if (infilp->f_mode & FMODE_NOCMTIME) |
97 | ioflags |= IO_INVIS; | ||
132 | 98 | ||
133 | STATIC ssize_t | ||
134 | xfs_file_splice_read_invis( | ||
135 | struct file *infilp, | ||
136 | loff_t *ppos, | ||
137 | struct pipe_inode_info *pipe, | ||
138 | size_t len, | ||
139 | unsigned int flags) | ||
140 | { | ||
141 | return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode), | 99 | return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode), |
142 | infilp, ppos, pipe, len, flags, IO_INVIS); | 100 | infilp, ppos, pipe, len, flags, ioflags); |
143 | } | 101 | } |
144 | 102 | ||
145 | STATIC ssize_t | 103 | STATIC ssize_t |
@@ -150,30 +108,49 @@ xfs_file_splice_write( | |||
150 | size_t len, | 108 | size_t len, |
151 | unsigned int flags) | 109 | unsigned int flags) |
152 | { | 110 | { |
153 | return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode), | 111 | int ioflags = 0; |
154 | pipe, outfilp, ppos, len, flags, 0); | 112 | |
155 | } | 113 | if (outfilp->f_mode & FMODE_NOCMTIME) |
114 | ioflags |= IO_INVIS; | ||
156 | 115 | ||
157 | STATIC ssize_t | ||
158 | xfs_file_splice_write_invis( | ||
159 | struct pipe_inode_info *pipe, | ||
160 | struct file *outfilp, | ||
161 | loff_t *ppos, | ||
162 | size_t len, | ||
163 | unsigned int flags) | ||
164 | { | ||
165 | return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode), | 116 | return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode), |
166 | pipe, outfilp, ppos, len, flags, IO_INVIS); | 117 | pipe, outfilp, ppos, len, flags, ioflags); |
167 | } | 118 | } |
168 | 119 | ||
169 | STATIC int | 120 | STATIC int |
170 | xfs_file_open( | 121 | xfs_file_open( |
171 | struct inode *inode, | 122 | struct inode *inode, |
172 | struct file *filp) | 123 | struct file *file) |
173 | { | 124 | { |
174 | if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) | 125 | if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) |
175 | return -EFBIG; | 126 | return -EFBIG; |
176 | return -xfs_open(XFS_I(inode)); | 127 | if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb))) |
128 | return -EIO; | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | STATIC int | ||
133 | xfs_dir_open( | ||
134 | struct inode *inode, | ||
135 | struct file *file) | ||
136 | { | ||
137 | struct xfs_inode *ip = XFS_I(inode); | ||
138 | int mode; | ||
139 | int error; | ||
140 | |||
141 | error = xfs_file_open(inode, file); | ||
142 | if (error) | ||
143 | return error; | ||
144 | |||
145 | /* | ||
146 | * If there are any blocks, read-ahead block 0 as we're almost | ||
147 | * certain to have the next operation be a read there. | ||
148 | */ | ||
149 | mode = xfs_ilock_map_shared(ip); | ||
150 | if (ip->i_d.di_nextents > 0) | ||
151 | xfs_da_reada_buf(NULL, ip, 0, XFS_DATA_FORK); | ||
152 | xfs_iunlock(ip, mode); | ||
153 | return 0; | ||
177 | } | 154 | } |
178 | 155 | ||
179 | STATIC int | 156 | STATIC int |
@@ -227,7 +204,7 @@ xfs_file_readdir( | |||
227 | * point we can change the ->readdir prototype to include the | 204 | * point we can change the ->readdir prototype to include the |
228 | * buffer size. | 205 | * buffer size. |
229 | */ | 206 | */ |
230 | bufsize = (size_t)min_t(loff_t, PAGE_SIZE, inode->i_size); | 207 | bufsize = (size_t)min_t(loff_t, PAGE_SIZE, ip->i_d.di_size); |
231 | 208 | ||
232 | error = xfs_readdir(ip, dirent, bufsize, | 209 | error = xfs_readdir(ip, dirent, bufsize, |
233 | (xfs_off_t *)&filp->f_pos, filldir); | 210 | (xfs_off_t *)&filp->f_pos, filldir); |
@@ -248,48 +225,6 @@ xfs_file_mmap( | |||
248 | return 0; | 225 | return 0; |
249 | } | 226 | } |
250 | 227 | ||
251 | STATIC long | ||
252 | xfs_file_ioctl( | ||
253 | struct file *filp, | ||
254 | unsigned int cmd, | ||
255 | unsigned long p) | ||
256 | { | ||
257 | int error; | ||
258 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
259 | |||
260 | error = xfs_ioctl(XFS_I(inode), filp, 0, cmd, (void __user *)p); | ||
261 | xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED); | ||
262 | |||
263 | /* NOTE: some of the ioctl's return positive #'s as a | ||
264 | * byte count indicating success, such as | ||
265 | * readlink_by_handle. So we don't "sign flip" | ||
266 | * like most other routines. This means true | ||
267 | * errors need to be returned as a negative value. | ||
268 | */ | ||
269 | return error; | ||
270 | } | ||
271 | |||
272 | STATIC long | ||
273 | xfs_file_ioctl_invis( | ||
274 | struct file *filp, | ||
275 | unsigned int cmd, | ||
276 | unsigned long p) | ||
277 | { | ||
278 | int error; | ||
279 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
280 | |||
281 | error = xfs_ioctl(XFS_I(inode), filp, IO_INVIS, cmd, (void __user *)p); | ||
282 | xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED); | ||
283 | |||
284 | /* NOTE: some of the ioctl's return positive #'s as a | ||
285 | * byte count indicating success, such as | ||
286 | * readlink_by_handle. So we don't "sign flip" | ||
287 | * like most other routines. This means true | ||
288 | * errors need to be returned as a negative value. | ||
289 | */ | ||
290 | return error; | ||
291 | } | ||
292 | |||
293 | /* | 228 | /* |
294 | * mmap()d file has taken write protection fault and is being made | 229 | * mmap()d file has taken write protection fault and is being made |
295 | * writable. We can set the page state up correctly for a writable | 230 | * writable. We can set the page state up correctly for a writable |
@@ -325,26 +260,8 @@ const struct file_operations xfs_file_operations = { | |||
325 | #endif | 260 | #endif |
326 | }; | 261 | }; |
327 | 262 | ||
328 | const struct file_operations xfs_invis_file_operations = { | ||
329 | .llseek = generic_file_llseek, | ||
330 | .read = do_sync_read, | ||
331 | .write = do_sync_write, | ||
332 | .aio_read = xfs_file_aio_read_invis, | ||
333 | .aio_write = xfs_file_aio_write_invis, | ||
334 | .splice_read = xfs_file_splice_read_invis, | ||
335 | .splice_write = xfs_file_splice_write_invis, | ||
336 | .unlocked_ioctl = xfs_file_ioctl_invis, | ||
337 | #ifdef CONFIG_COMPAT | ||
338 | .compat_ioctl = xfs_file_compat_invis_ioctl, | ||
339 | #endif | ||
340 | .mmap = xfs_file_mmap, | ||
341 | .open = xfs_file_open, | ||
342 | .release = xfs_file_release, | ||
343 | .fsync = xfs_file_fsync, | ||
344 | }; | ||
345 | |||
346 | |||
347 | const struct file_operations xfs_dir_file_operations = { | 263 | const struct file_operations xfs_dir_file_operations = { |
264 | .open = xfs_dir_open, | ||
348 | .read = generic_read_dir, | 265 | .read = generic_read_dir, |
349 | .readdir = xfs_file_readdir, | 266 | .readdir = xfs_file_readdir, |
350 | .llseek = generic_file_llseek, | 267 | .llseek = generic_file_llseek, |
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index 36caa6d957df..5aeb77776961 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c | |||
@@ -24,6 +24,10 @@ int fs_noerr(void) { return 0; } | |||
24 | int fs_nosys(void) { return ENOSYS; } | 24 | int fs_nosys(void) { return ENOSYS; } |
25 | void fs_noval(void) { return; } | 25 | void fs_noval(void) { return; } |
26 | 26 | ||
27 | /* | ||
28 | * note: all filemap functions return negative error codes. These | ||
29 | * need to be inverted before returning to the xfs core functions. | ||
30 | */ | ||
27 | void | 31 | void |
28 | xfs_tosspages( | 32 | xfs_tosspages( |
29 | xfs_inode_t *ip, | 33 | xfs_inode_t *ip, |
@@ -53,7 +57,7 @@ xfs_flushinval_pages( | |||
53 | if (!ret) | 57 | if (!ret) |
54 | truncate_inode_pages(mapping, first); | 58 | truncate_inode_pages(mapping, first); |
55 | } | 59 | } |
56 | return ret; | 60 | return -ret; |
57 | } | 61 | } |
58 | 62 | ||
59 | int | 63 | int |
@@ -72,10 +76,23 @@ xfs_flush_pages( | |||
72 | xfs_iflags_clear(ip, XFS_ITRUNCATED); | 76 | xfs_iflags_clear(ip, XFS_ITRUNCATED); |
73 | ret = filemap_fdatawrite(mapping); | 77 | ret = filemap_fdatawrite(mapping); |
74 | if (flags & XFS_B_ASYNC) | 78 | if (flags & XFS_B_ASYNC) |
75 | return ret; | 79 | return -ret; |
76 | ret2 = filemap_fdatawait(mapping); | 80 | ret2 = filemap_fdatawait(mapping); |
77 | if (!ret) | 81 | if (!ret) |
78 | ret = ret2; | 82 | ret = ret2; |
79 | } | 83 | } |
80 | return ret; | 84 | return -ret; |
85 | } | ||
86 | |||
87 | int | ||
88 | xfs_wait_on_pages( | ||
89 | xfs_inode_t *ip, | ||
90 | xfs_off_t first, | ||
91 | xfs_off_t last) | ||
92 | { | ||
93 | struct address_space *mapping = VFS_I(ip)->i_mapping; | ||
94 | |||
95 | if (mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK)) | ||
96 | return -filemap_fdatawait(mapping); | ||
97 | return 0; | ||
81 | } | 98 | } |
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c index ef90e64641e6..2ae8b1ccb02e 100644 --- a/fs/xfs/linux-2.6/xfs_globals.c +++ b/fs/xfs/linux-2.6/xfs_globals.c | |||
@@ -26,7 +26,6 @@ | |||
26 | */ | 26 | */ |
27 | xfs_param_t xfs_params = { | 27 | xfs_param_t xfs_params = { |
28 | /* MIN DFLT MAX */ | 28 | /* MIN DFLT MAX */ |
29 | .restrict_chown = { 0, 1, 1 }, | ||
30 | .sgid_inherit = { 0, 0, 1 }, | 29 | .sgid_inherit = { 0, 0, 1 }, |
31 | .symlink_mode = { 0, 0, 1 }, | 30 | .symlink_mode = { 0, 0, 1 }, |
32 | .panic_mask = { 0, 0, 255 }, | 31 | .panic_mask = { 0, 0, 255 }, |
@@ -43,10 +42,3 @@ xfs_param_t xfs_params = { | |||
43 | .inherit_nodfrg = { 0, 1, 1 }, | 42 | .inherit_nodfrg = { 0, 1, 1 }, |
44 | .fstrm_timer = { 1, 30*100, 3600*100}, | 43 | .fstrm_timer = { 1, 30*100, 3600*100}, |
45 | }; | 44 | }; |
46 | |||
47 | /* | ||
48 | * Global system credential structure. | ||
49 | */ | ||
50 | static cred_t sys_cred_val; | ||
51 | cred_t *sys_cred = &sys_cred_val; | ||
52 | |||
diff --git a/fs/xfs/linux-2.6/xfs_globals.h b/fs/xfs/linux-2.6/xfs_globals.h index 6eda8a3eb6f1..69f71caf061c 100644 --- a/fs/xfs/linux-2.6/xfs_globals.h +++ b/fs/xfs/linux-2.6/xfs_globals.h | |||
@@ -19,6 +19,5 @@ | |||
19 | #define __XFS_GLOBALS_H__ | 19 | #define __XFS_GLOBALS_H__ |
20 | 20 | ||
21 | extern uint64_t xfs_panic_mask; /* set to cause more panics */ | 21 | extern uint64_t xfs_panic_mask; /* set to cause more panics */ |
22 | extern cred_t *sys_cred; | ||
23 | 22 | ||
24 | #endif /* __XFS_GLOBALS_H__ */ | 23 | #endif /* __XFS_GLOBALS_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 281cbd5a25cf..67205f6198ba 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -68,26 +68,22 @@ | |||
68 | * XFS_IOC_PATH_TO_HANDLE | 68 | * XFS_IOC_PATH_TO_HANDLE |
69 | * returns full handle for a path | 69 | * returns full handle for a path |
70 | */ | 70 | */ |
71 | STATIC int | 71 | int |
72 | xfs_find_handle( | 72 | xfs_find_handle( |
73 | unsigned int cmd, | 73 | unsigned int cmd, |
74 | void __user *arg) | 74 | xfs_fsop_handlereq_t *hreq) |
75 | { | 75 | { |
76 | int hsize; | 76 | int hsize; |
77 | xfs_handle_t handle; | 77 | xfs_handle_t handle; |
78 | xfs_fsop_handlereq_t hreq; | ||
79 | struct inode *inode; | 78 | struct inode *inode; |
80 | 79 | ||
81 | if (copy_from_user(&hreq, arg, sizeof(hreq))) | ||
82 | return -XFS_ERROR(EFAULT); | ||
83 | |||
84 | memset((char *)&handle, 0, sizeof(handle)); | 80 | memset((char *)&handle, 0, sizeof(handle)); |
85 | 81 | ||
86 | switch (cmd) { | 82 | switch (cmd) { |
87 | case XFS_IOC_PATH_TO_FSHANDLE: | 83 | case XFS_IOC_PATH_TO_FSHANDLE: |
88 | case XFS_IOC_PATH_TO_HANDLE: { | 84 | case XFS_IOC_PATH_TO_HANDLE: { |
89 | struct path path; | 85 | struct path path; |
90 | int error = user_lpath((const char __user *)hreq.path, &path); | 86 | int error = user_lpath((const char __user *)hreq->path, &path); |
91 | if (error) | 87 | if (error) |
92 | return error; | 88 | return error; |
93 | 89 | ||
@@ -101,7 +97,7 @@ xfs_find_handle( | |||
101 | case XFS_IOC_FD_TO_HANDLE: { | 97 | case XFS_IOC_FD_TO_HANDLE: { |
102 | struct file *file; | 98 | struct file *file; |
103 | 99 | ||
104 | file = fget(hreq.fd); | 100 | file = fget(hreq->fd); |
105 | if (!file) | 101 | if (!file) |
106 | return -EBADF; | 102 | return -EBADF; |
107 | 103 | ||
@@ -158,8 +154,8 @@ xfs_find_handle( | |||
158 | } | 154 | } |
159 | 155 | ||
160 | /* now copy our handle into the user buffer & write out the size */ | 156 | /* now copy our handle into the user buffer & write out the size */ |
161 | if (copy_to_user(hreq.ohandle, &handle, hsize) || | 157 | if (copy_to_user(hreq->ohandle, &handle, hsize) || |
162 | copy_to_user(hreq.ohandlen, &hsize, sizeof(__s32))) { | 158 | copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) { |
163 | iput(inode); | 159 | iput(inode); |
164 | return -XFS_ERROR(EFAULT); | 160 | return -XFS_ERROR(EFAULT); |
165 | } | 161 | } |
@@ -249,10 +245,10 @@ xfs_vget_fsop_handlereq( | |||
249 | return 0; | 245 | return 0; |
250 | } | 246 | } |
251 | 247 | ||
252 | STATIC int | 248 | int |
253 | xfs_open_by_handle( | 249 | xfs_open_by_handle( |
254 | xfs_mount_t *mp, | 250 | xfs_mount_t *mp, |
255 | void __user *arg, | 251 | xfs_fsop_handlereq_t *hreq, |
256 | struct file *parfilp, | 252 | struct file *parfilp, |
257 | struct inode *parinode) | 253 | struct inode *parinode) |
258 | { | 254 | { |
@@ -263,14 +259,11 @@ xfs_open_by_handle( | |||
263 | struct file *filp; | 259 | struct file *filp; |
264 | struct inode *inode; | 260 | struct inode *inode; |
265 | struct dentry *dentry; | 261 | struct dentry *dentry; |
266 | xfs_fsop_handlereq_t hreq; | ||
267 | 262 | ||
268 | if (!capable(CAP_SYS_ADMIN)) | 263 | if (!capable(CAP_SYS_ADMIN)) |
269 | return -XFS_ERROR(EPERM); | 264 | return -XFS_ERROR(EPERM); |
270 | if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) | ||
271 | return -XFS_ERROR(EFAULT); | ||
272 | 265 | ||
273 | error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode); | 266 | error = xfs_vget_fsop_handlereq(mp, parinode, hreq, &inode); |
274 | if (error) | 267 | if (error) |
275 | return -error; | 268 | return -error; |
276 | 269 | ||
@@ -281,10 +274,10 @@ xfs_open_by_handle( | |||
281 | } | 274 | } |
282 | 275 | ||
283 | #if BITS_PER_LONG != 32 | 276 | #if BITS_PER_LONG != 32 |
284 | hreq.oflags |= O_LARGEFILE; | 277 | hreq->oflags |= O_LARGEFILE; |
285 | #endif | 278 | #endif |
286 | /* Put open permission in namei format. */ | 279 | /* Put open permission in namei format. */ |
287 | permflag = hreq.oflags; | 280 | permflag = hreq->oflags; |
288 | if ((permflag+1) & O_ACCMODE) | 281 | if ((permflag+1) & O_ACCMODE) |
289 | permflag++; | 282 | permflag++; |
290 | if (permflag & O_TRUNC) | 283 | if (permflag & O_TRUNC) |
@@ -322,15 +315,16 @@ xfs_open_by_handle( | |||
322 | mntget(parfilp->f_path.mnt); | 315 | mntget(parfilp->f_path.mnt); |
323 | 316 | ||
324 | /* Create file pointer. */ | 317 | /* Create file pointer. */ |
325 | filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags, cred); | 318 | filp = dentry_open(dentry, parfilp->f_path.mnt, hreq->oflags, cred); |
326 | if (IS_ERR(filp)) { | 319 | if (IS_ERR(filp)) { |
327 | put_unused_fd(new_fd); | 320 | put_unused_fd(new_fd); |
328 | return -XFS_ERROR(-PTR_ERR(filp)); | 321 | return -XFS_ERROR(-PTR_ERR(filp)); |
329 | } | 322 | } |
323 | |||
330 | if (inode->i_mode & S_IFREG) { | 324 | if (inode->i_mode & S_IFREG) { |
331 | /* invisible operation should not change atime */ | 325 | /* invisible operation should not change atime */ |
332 | filp->f_flags |= O_NOATIME; | 326 | filp->f_flags |= O_NOATIME; |
333 | filp->f_op = &xfs_invis_file_operations; | 327 | filp->f_mode |= FMODE_NOCMTIME; |
334 | } | 328 | } |
335 | 329 | ||
336 | fd_install(new_fd, filp); | 330 | fd_install(new_fd, filp); |
@@ -363,24 +357,21 @@ do_readlink( | |||
363 | } | 357 | } |
364 | 358 | ||
365 | 359 | ||
366 | STATIC int | 360 | int |
367 | xfs_readlink_by_handle( | 361 | xfs_readlink_by_handle( |
368 | xfs_mount_t *mp, | 362 | xfs_mount_t *mp, |
369 | void __user *arg, | 363 | xfs_fsop_handlereq_t *hreq, |
370 | struct inode *parinode) | 364 | struct inode *parinode) |
371 | { | 365 | { |
372 | struct inode *inode; | 366 | struct inode *inode; |
373 | xfs_fsop_handlereq_t hreq; | ||
374 | __u32 olen; | 367 | __u32 olen; |
375 | void *link; | 368 | void *link; |
376 | int error; | 369 | int error; |
377 | 370 | ||
378 | if (!capable(CAP_SYS_ADMIN)) | 371 | if (!capable(CAP_SYS_ADMIN)) |
379 | return -XFS_ERROR(EPERM); | 372 | return -XFS_ERROR(EPERM); |
380 | if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) | ||
381 | return -XFS_ERROR(EFAULT); | ||
382 | 373 | ||
383 | error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode); | 374 | error = xfs_vget_fsop_handlereq(mp, parinode, hreq, &inode); |
384 | if (error) | 375 | if (error) |
385 | return -error; | 376 | return -error; |
386 | 377 | ||
@@ -390,7 +381,7 @@ xfs_readlink_by_handle( | |||
390 | goto out_iput; | 381 | goto out_iput; |
391 | } | 382 | } |
392 | 383 | ||
393 | if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) { | 384 | if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) { |
394 | error = -XFS_ERROR(EFAULT); | 385 | error = -XFS_ERROR(EFAULT); |
395 | goto out_iput; | 386 | goto out_iput; |
396 | } | 387 | } |
@@ -402,7 +393,7 @@ xfs_readlink_by_handle( | |||
402 | error = -xfs_readlink(XFS_I(inode), link); | 393 | error = -xfs_readlink(XFS_I(inode), link); |
403 | if (error) | 394 | if (error) |
404 | goto out_kfree; | 395 | goto out_kfree; |
405 | error = do_readlink(hreq.ohandle, olen, link); | 396 | error = do_readlink(hreq->ohandle, olen, link); |
406 | if (error) | 397 | if (error) |
407 | goto out_kfree; | 398 | goto out_kfree; |
408 | 399 | ||
@@ -501,7 +492,7 @@ xfs_attrlist_by_handle( | |||
501 | return -error; | 492 | return -error; |
502 | } | 493 | } |
503 | 494 | ||
504 | STATIC int | 495 | int |
505 | xfs_attrmulti_attr_get( | 496 | xfs_attrmulti_attr_get( |
506 | struct inode *inode, | 497 | struct inode *inode, |
507 | char *name, | 498 | char *name, |
@@ -530,7 +521,7 @@ xfs_attrmulti_attr_get( | |||
530 | return error; | 521 | return error; |
531 | } | 522 | } |
532 | 523 | ||
533 | STATIC int | 524 | int |
534 | xfs_attrmulti_attr_set( | 525 | xfs_attrmulti_attr_set( |
535 | struct inode *inode, | 526 | struct inode *inode, |
536 | char *name, | 527 | char *name, |
@@ -560,7 +551,7 @@ xfs_attrmulti_attr_set( | |||
560 | return error; | 551 | return error; |
561 | } | 552 | } |
562 | 553 | ||
563 | STATIC int | 554 | int |
564 | xfs_attrmulti_attr_remove( | 555 | xfs_attrmulti_attr_remove( |
565 | struct inode *inode, | 556 | struct inode *inode, |
566 | char *name, | 557 | char *name, |
@@ -662,19 +653,26 @@ xfs_attrmulti_by_handle( | |||
662 | return -error; | 653 | return -error; |
663 | } | 654 | } |
664 | 655 | ||
665 | STATIC int | 656 | int |
666 | xfs_ioc_space( | 657 | xfs_ioc_space( |
667 | struct xfs_inode *ip, | 658 | struct xfs_inode *ip, |
668 | struct inode *inode, | 659 | struct inode *inode, |
669 | struct file *filp, | 660 | struct file *filp, |
670 | int ioflags, | 661 | int ioflags, |
671 | unsigned int cmd, | 662 | unsigned int cmd, |
672 | void __user *arg) | 663 | xfs_flock64_t *bf) |
673 | { | 664 | { |
674 | xfs_flock64_t bf; | ||
675 | int attr_flags = 0; | 665 | int attr_flags = 0; |
676 | int error; | 666 | int error; |
677 | 667 | ||
668 | /* | ||
669 | * Only allow the sys admin to reserve space unless | ||
670 | * unwritten extents are enabled. | ||
671 | */ | ||
672 | if (!xfs_sb_version_hasextflgbit(&ip->i_mount->m_sb) && | ||
673 | !capable(CAP_SYS_ADMIN)) | ||
674 | return -XFS_ERROR(EPERM); | ||
675 | |||
678 | if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) | 676 | if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) |
679 | return -XFS_ERROR(EPERM); | 677 | return -XFS_ERROR(EPERM); |
680 | 678 | ||
@@ -684,16 +682,12 @@ xfs_ioc_space( | |||
684 | if (!S_ISREG(inode->i_mode)) | 682 | if (!S_ISREG(inode->i_mode)) |
685 | return -XFS_ERROR(EINVAL); | 683 | return -XFS_ERROR(EINVAL); |
686 | 684 | ||
687 | if (copy_from_user(&bf, arg, sizeof(bf))) | ||
688 | return -XFS_ERROR(EFAULT); | ||
689 | |||
690 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) | 685 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) |
691 | attr_flags |= XFS_ATTR_NONBLOCK; | 686 | attr_flags |= XFS_ATTR_NONBLOCK; |
692 | if (ioflags & IO_INVIS) | 687 | if (ioflags & IO_INVIS) |
693 | attr_flags |= XFS_ATTR_DMI; | 688 | attr_flags |= XFS_ATTR_DMI; |
694 | 689 | ||
695 | error = xfs_change_file_space(ip, cmd, &bf, filp->f_pos, | 690 | error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); |
696 | NULL, attr_flags); | ||
697 | return -error; | 691 | return -error; |
698 | } | 692 | } |
699 | 693 | ||
@@ -1105,10 +1099,6 @@ xfs_ioctl_setattr( | |||
1105 | 1099 | ||
1106 | /* | 1100 | /* |
1107 | * Change file ownership. Must be the owner or privileged. | 1101 | * Change file ownership. Must be the owner or privileged. |
1108 | * If the system was configured with the "restricted_chown" | ||
1109 | * option, the owner is not permitted to give away the file, | ||
1110 | * and can change the group id only to a group of which he | ||
1111 | * or she is a member. | ||
1112 | */ | 1102 | */ |
1113 | if (mask & FSX_PROJID) { | 1103 | if (mask & FSX_PROJID) { |
1114 | /* | 1104 | /* |
@@ -1137,7 +1127,7 @@ xfs_ioctl_setattr( | |||
1137 | * the superblock version number since projids didn't | 1127 | * the superblock version number since projids didn't |
1138 | * exist before DINODE_VERSION_2 and SB_VERSION_NLINK. | 1128 | * exist before DINODE_VERSION_2 and SB_VERSION_NLINK. |
1139 | */ | 1129 | */ |
1140 | if (ip->i_d.di_version == XFS_DINODE_VERSION_1) | 1130 | if (ip->i_d.di_version == 1) |
1141 | xfs_bump_ino_vers2(tp, ip); | 1131 | xfs_bump_ino_vers2(tp, ip); |
1142 | } | 1132 | } |
1143 | 1133 | ||
@@ -1256,43 +1246,67 @@ xfs_ioc_setxflags( | |||
1256 | } | 1246 | } |
1257 | 1247 | ||
1258 | STATIC int | 1248 | STATIC int |
1249 | xfs_getbmap_format(void **ap, struct getbmapx *bmv, int *full) | ||
1250 | { | ||
1251 | struct getbmap __user *base = *ap; | ||
1252 | |||
1253 | /* copy only getbmap portion (not getbmapx) */ | ||
1254 | if (copy_to_user(base, bmv, sizeof(struct getbmap))) | ||
1255 | return XFS_ERROR(EFAULT); | ||
1256 | |||
1257 | *ap += sizeof(struct getbmap); | ||
1258 | return 0; | ||
1259 | } | ||
1260 | |||
1261 | STATIC int | ||
1259 | xfs_ioc_getbmap( | 1262 | xfs_ioc_getbmap( |
1260 | struct xfs_inode *ip, | 1263 | struct xfs_inode *ip, |
1261 | int ioflags, | 1264 | int ioflags, |
1262 | unsigned int cmd, | 1265 | unsigned int cmd, |
1263 | void __user *arg) | 1266 | void __user *arg) |
1264 | { | 1267 | { |
1265 | struct getbmap bm; | 1268 | struct getbmapx bmx; |
1266 | int iflags; | ||
1267 | int error; | 1269 | int error; |
1268 | 1270 | ||
1269 | if (copy_from_user(&bm, arg, sizeof(bm))) | 1271 | if (copy_from_user(&bmx, arg, sizeof(struct getbmapx))) |
1270 | return -XFS_ERROR(EFAULT); | 1272 | return -XFS_ERROR(EFAULT); |
1271 | 1273 | ||
1272 | if (bm.bmv_count < 2) | 1274 | if (bmx.bmv_count < 2) |
1273 | return -XFS_ERROR(EINVAL); | 1275 | return -XFS_ERROR(EINVAL); |
1274 | 1276 | ||
1275 | iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0); | 1277 | bmx.bmv_iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0); |
1276 | if (ioflags & IO_INVIS) | 1278 | if (ioflags & IO_INVIS) |
1277 | iflags |= BMV_IF_NO_DMAPI_READ; | 1279 | bmx.bmv_iflags |= BMV_IF_NO_DMAPI_READ; |
1278 | 1280 | ||
1279 | error = xfs_getbmap(ip, &bm, (struct getbmap __user *)arg+1, iflags); | 1281 | error = xfs_getbmap(ip, &bmx, xfs_getbmap_format, |
1282 | (struct getbmap *)arg+1); | ||
1280 | if (error) | 1283 | if (error) |
1281 | return -error; | 1284 | return -error; |
1282 | 1285 | ||
1283 | if (copy_to_user(arg, &bm, sizeof(bm))) | 1286 | /* copy back header - only size of getbmap */ |
1287 | if (copy_to_user(arg, &bmx, sizeof(struct getbmap))) | ||
1284 | return -XFS_ERROR(EFAULT); | 1288 | return -XFS_ERROR(EFAULT); |
1285 | return 0; | 1289 | return 0; |
1286 | } | 1290 | } |
1287 | 1291 | ||
1288 | STATIC int | 1292 | STATIC int |
1293 | xfs_getbmapx_format(void **ap, struct getbmapx *bmv, int *full) | ||
1294 | { | ||
1295 | struct getbmapx __user *base = *ap; | ||
1296 | |||
1297 | if (copy_to_user(base, bmv, sizeof(struct getbmapx))) | ||
1298 | return XFS_ERROR(EFAULT); | ||
1299 | |||
1300 | *ap += sizeof(struct getbmapx); | ||
1301 | return 0; | ||
1302 | } | ||
1303 | |||
1304 | STATIC int | ||
1289 | xfs_ioc_getbmapx( | 1305 | xfs_ioc_getbmapx( |
1290 | struct xfs_inode *ip, | 1306 | struct xfs_inode *ip, |
1291 | void __user *arg) | 1307 | void __user *arg) |
1292 | { | 1308 | { |
1293 | struct getbmapx bmx; | 1309 | struct getbmapx bmx; |
1294 | struct getbmap bm; | ||
1295 | int iflags; | ||
1296 | int error; | 1310 | int error; |
1297 | 1311 | ||
1298 | if (copy_from_user(&bmx, arg, sizeof(bmx))) | 1312 | if (copy_from_user(&bmx, arg, sizeof(bmx))) |
@@ -1301,46 +1315,46 @@ xfs_ioc_getbmapx( | |||
1301 | if (bmx.bmv_count < 2) | 1315 | if (bmx.bmv_count < 2) |
1302 | return -XFS_ERROR(EINVAL); | 1316 | return -XFS_ERROR(EINVAL); |
1303 | 1317 | ||
1304 | /* | 1318 | if (bmx.bmv_iflags & (~BMV_IF_VALID)) |
1305 | * Map input getbmapx structure to a getbmap | ||
1306 | * structure for xfs_getbmap. | ||
1307 | */ | ||
1308 | GETBMAP_CONVERT(bmx, bm); | ||
1309 | |||
1310 | iflags = bmx.bmv_iflags; | ||
1311 | |||
1312 | if (iflags & (~BMV_IF_VALID)) | ||
1313 | return -XFS_ERROR(EINVAL); | 1319 | return -XFS_ERROR(EINVAL); |
1314 | 1320 | ||
1315 | iflags |= BMV_IF_EXTENDED; | 1321 | error = xfs_getbmap(ip, &bmx, xfs_getbmapx_format, |
1316 | 1322 | (struct getbmapx *)arg+1); | |
1317 | error = xfs_getbmap(ip, &bm, (struct getbmapx __user *)arg+1, iflags); | ||
1318 | if (error) | 1323 | if (error) |
1319 | return -error; | 1324 | return -error; |
1320 | 1325 | ||
1321 | GETBMAP_CONVERT(bm, bmx); | 1326 | /* copy back header */ |
1322 | 1327 | if (copy_to_user(arg, &bmx, sizeof(struct getbmapx))) | |
1323 | if (copy_to_user(arg, &bmx, sizeof(bmx))) | ||
1324 | return -XFS_ERROR(EFAULT); | 1328 | return -XFS_ERROR(EFAULT); |
1325 | 1329 | ||
1326 | return 0; | 1330 | return 0; |
1327 | } | 1331 | } |
1328 | 1332 | ||
1329 | int | 1333 | /* |
1330 | xfs_ioctl( | 1334 | * Note: some of the ioctl's return positive numbers as a |
1331 | xfs_inode_t *ip, | 1335 | * byte count indicating success, such as readlink_by_handle. |
1336 | * So we don't "sign flip" like most other routines. This means | ||
1337 | * true errors need to be returned as a negative value. | ||
1338 | */ | ||
1339 | long | ||
1340 | xfs_file_ioctl( | ||
1332 | struct file *filp, | 1341 | struct file *filp, |
1333 | int ioflags, | ||
1334 | unsigned int cmd, | 1342 | unsigned int cmd, |
1335 | void __user *arg) | 1343 | unsigned long p) |
1336 | { | 1344 | { |
1337 | struct inode *inode = filp->f_path.dentry->d_inode; | 1345 | struct inode *inode = filp->f_path.dentry->d_inode; |
1338 | xfs_mount_t *mp = ip->i_mount; | 1346 | struct xfs_inode *ip = XFS_I(inode); |
1347 | struct xfs_mount *mp = ip->i_mount; | ||
1348 | void __user *arg = (void __user *)p; | ||
1349 | int ioflags = 0; | ||
1339 | int error; | 1350 | int error; |
1340 | 1351 | ||
1341 | xfs_itrace_entry(XFS_I(inode)); | 1352 | if (filp->f_mode & FMODE_NOCMTIME) |
1342 | switch (cmd) { | 1353 | ioflags |= IO_INVIS; |
1343 | 1354 | ||
1355 | xfs_itrace_entry(ip); | ||
1356 | |||
1357 | switch (cmd) { | ||
1344 | case XFS_IOC_ALLOCSP: | 1358 | case XFS_IOC_ALLOCSP: |
1345 | case XFS_IOC_FREESP: | 1359 | case XFS_IOC_FREESP: |
1346 | case XFS_IOC_RESVSP: | 1360 | case XFS_IOC_RESVSP: |
@@ -1348,17 +1362,13 @@ xfs_ioctl( | |||
1348 | case XFS_IOC_ALLOCSP64: | 1362 | case XFS_IOC_ALLOCSP64: |
1349 | case XFS_IOC_FREESP64: | 1363 | case XFS_IOC_FREESP64: |
1350 | case XFS_IOC_RESVSP64: | 1364 | case XFS_IOC_RESVSP64: |
1351 | case XFS_IOC_UNRESVSP64: | 1365 | case XFS_IOC_UNRESVSP64: { |
1352 | /* | 1366 | xfs_flock64_t bf; |
1353 | * Only allow the sys admin to reserve space unless | ||
1354 | * unwritten extents are enabled. | ||
1355 | */ | ||
1356 | if (!xfs_sb_version_hasextflgbit(&mp->m_sb) && | ||
1357 | !capable(CAP_SYS_ADMIN)) | ||
1358 | return -EPERM; | ||
1359 | |||
1360 | return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg); | ||
1361 | 1367 | ||
1368 | if (copy_from_user(&bf, arg, sizeof(bf))) | ||
1369 | return -XFS_ERROR(EFAULT); | ||
1370 | return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf); | ||
1371 | } | ||
1362 | case XFS_IOC_DIOINFO: { | 1372 | case XFS_IOC_DIOINFO: { |
1363 | struct dioattr da; | 1373 | struct dioattr da; |
1364 | xfs_buftarg_t *target = | 1374 | xfs_buftarg_t *target = |
@@ -1418,18 +1428,30 @@ xfs_ioctl( | |||
1418 | 1428 | ||
1419 | case XFS_IOC_FD_TO_HANDLE: | 1429 | case XFS_IOC_FD_TO_HANDLE: |
1420 | case XFS_IOC_PATH_TO_HANDLE: | 1430 | case XFS_IOC_PATH_TO_HANDLE: |
1421 | case XFS_IOC_PATH_TO_FSHANDLE: | 1431 | case XFS_IOC_PATH_TO_FSHANDLE: { |
1422 | return xfs_find_handle(cmd, arg); | 1432 | xfs_fsop_handlereq_t hreq; |
1423 | 1433 | ||
1424 | case XFS_IOC_OPEN_BY_HANDLE: | 1434 | if (copy_from_user(&hreq, arg, sizeof(hreq))) |
1425 | return xfs_open_by_handle(mp, arg, filp, inode); | 1435 | return -XFS_ERROR(EFAULT); |
1436 | return xfs_find_handle(cmd, &hreq); | ||
1437 | } | ||
1438 | case XFS_IOC_OPEN_BY_HANDLE: { | ||
1439 | xfs_fsop_handlereq_t hreq; | ||
1426 | 1440 | ||
1441 | if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) | ||
1442 | return -XFS_ERROR(EFAULT); | ||
1443 | return xfs_open_by_handle(mp, &hreq, filp, inode); | ||
1444 | } | ||
1427 | case XFS_IOC_FSSETDM_BY_HANDLE: | 1445 | case XFS_IOC_FSSETDM_BY_HANDLE: |
1428 | return xfs_fssetdm_by_handle(mp, arg, inode); | 1446 | return xfs_fssetdm_by_handle(mp, arg, inode); |
1429 | 1447 | ||
1430 | case XFS_IOC_READLINK_BY_HANDLE: | 1448 | case XFS_IOC_READLINK_BY_HANDLE: { |
1431 | return xfs_readlink_by_handle(mp, arg, inode); | 1449 | xfs_fsop_handlereq_t hreq; |
1432 | 1450 | ||
1451 | if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) | ||
1452 | return -XFS_ERROR(EFAULT); | ||
1453 | return xfs_readlink_by_handle(mp, &hreq, inode); | ||
1454 | } | ||
1433 | case XFS_IOC_ATTRLIST_BY_HANDLE: | 1455 | case XFS_IOC_ATTRLIST_BY_HANDLE: |
1434 | return xfs_attrlist_by_handle(mp, arg, inode); | 1456 | return xfs_attrlist_by_handle(mp, arg, inode); |
1435 | 1457 | ||
@@ -1437,7 +1459,11 @@ xfs_ioctl( | |||
1437 | return xfs_attrmulti_by_handle(mp, arg, filp, inode); | 1459 | return xfs_attrmulti_by_handle(mp, arg, filp, inode); |
1438 | 1460 | ||
1439 | case XFS_IOC_SWAPEXT: { | 1461 | case XFS_IOC_SWAPEXT: { |
1440 | error = xfs_swapext((struct xfs_swapext __user *)arg); | 1462 | struct xfs_swapext sxp; |
1463 | |||
1464 | if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t))) | ||
1465 | return -XFS_ERROR(EFAULT); | ||
1466 | error = xfs_swapext(&sxp); | ||
1441 | return -error; | 1467 | return -error; |
1442 | } | 1468 | } |
1443 | 1469 | ||
@@ -1493,9 +1519,6 @@ xfs_ioctl( | |||
1493 | case XFS_IOC_FSGROWFSDATA: { | 1519 | case XFS_IOC_FSGROWFSDATA: { |
1494 | xfs_growfs_data_t in; | 1520 | xfs_growfs_data_t in; |
1495 | 1521 | ||
1496 | if (!capable(CAP_SYS_ADMIN)) | ||
1497 | return -EPERM; | ||
1498 | |||
1499 | if (copy_from_user(&in, arg, sizeof(in))) | 1522 | if (copy_from_user(&in, arg, sizeof(in))) |
1500 | return -XFS_ERROR(EFAULT); | 1523 | return -XFS_ERROR(EFAULT); |
1501 | 1524 | ||
@@ -1506,9 +1529,6 @@ xfs_ioctl( | |||
1506 | case XFS_IOC_FSGROWFSLOG: { | 1529 | case XFS_IOC_FSGROWFSLOG: { |
1507 | xfs_growfs_log_t in; | 1530 | xfs_growfs_log_t in; |
1508 | 1531 | ||
1509 | if (!capable(CAP_SYS_ADMIN)) | ||
1510 | return -EPERM; | ||
1511 | |||
1512 | if (copy_from_user(&in, arg, sizeof(in))) | 1532 | if (copy_from_user(&in, arg, sizeof(in))) |
1513 | return -XFS_ERROR(EFAULT); | 1533 | return -XFS_ERROR(EFAULT); |
1514 | 1534 | ||
@@ -1519,9 +1539,6 @@ xfs_ioctl( | |||
1519 | case XFS_IOC_FSGROWFSRT: { | 1539 | case XFS_IOC_FSGROWFSRT: { |
1520 | xfs_growfs_rt_t in; | 1540 | xfs_growfs_rt_t in; |
1521 | 1541 | ||
1522 | if (!capable(CAP_SYS_ADMIN)) | ||
1523 | return -EPERM; | ||
1524 | |||
1525 | if (copy_from_user(&in, arg, sizeof(in))) | 1542 | if (copy_from_user(&in, arg, sizeof(in))) |
1526 | return -XFS_ERROR(EFAULT); | 1543 | return -XFS_ERROR(EFAULT); |
1527 | 1544 | ||
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.h b/fs/xfs/linux-2.6/xfs_ioctl.h new file mode 100644 index 000000000000..8c16bf2d7e03 --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_ioctl.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_IOCTL_H__ | ||
19 | #define __XFS_IOCTL_H__ | ||
20 | |||
21 | extern int | ||
22 | xfs_ioc_space( | ||
23 | struct xfs_inode *ip, | ||
24 | struct inode *inode, | ||
25 | struct file *filp, | ||
26 | int ioflags, | ||
27 | unsigned int cmd, | ||
28 | xfs_flock64_t *bf); | ||
29 | |||
30 | extern int | ||
31 | xfs_find_handle( | ||
32 | unsigned int cmd, | ||
33 | xfs_fsop_handlereq_t *hreq); | ||
34 | |||
35 | extern int | ||
36 | xfs_open_by_handle( | ||
37 | xfs_mount_t *mp, | ||
38 | xfs_fsop_handlereq_t *hreq, | ||
39 | struct file *parfilp, | ||
40 | struct inode *parinode); | ||
41 | |||
42 | extern int | ||
43 | xfs_readlink_by_handle( | ||
44 | xfs_mount_t *mp, | ||
45 | xfs_fsop_handlereq_t *hreq, | ||
46 | struct inode *parinode); | ||
47 | |||
48 | extern int | ||
49 | xfs_attrmulti_attr_get( | ||
50 | struct inode *inode, | ||
51 | char *name, | ||
52 | char __user *ubuf, | ||
53 | __uint32_t *len, | ||
54 | __uint32_t flags); | ||
55 | |||
56 | extern int | ||
57 | xfs_attrmulti_attr_set( | ||
58 | struct inode *inode, | ||
59 | char *name, | ||
60 | const char __user *ubuf, | ||
61 | __uint32_t len, | ||
62 | __uint32_t flags); | ||
63 | |||
64 | extern int | ||
65 | xfs_attrmulti_attr_remove( | ||
66 | struct inode *inode, | ||
67 | char *name, | ||
68 | __uint32_t flags); | ||
69 | |||
70 | extern long | ||
71 | xfs_file_ioctl( | ||
72 | struct file *filp, | ||
73 | unsigned int cmd, | ||
74 | unsigned long p); | ||
75 | |||
76 | extern long | ||
77 | xfs_file_compat_ioctl( | ||
78 | struct file *file, | ||
79 | unsigned int cmd, | ||
80 | unsigned long arg); | ||
81 | |||
82 | #endif | ||
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index a4b254eb43b2..0504cece9f66 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
@@ -16,11 +16,7 @@ | |||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include <linux/compat.h> | 18 | #include <linux/compat.h> |
19 | #include <linux/init.h> | ||
20 | #include <linux/ioctl.h> | 19 | #include <linux/ioctl.h> |
21 | #include <linux/syscalls.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
25 | #include "xfs.h" | 21 | #include "xfs.h" |
26 | #include "xfs_fs.h" | 22 | #include "xfs_fs.h" |
@@ -36,7 +32,6 @@ | |||
36 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
37 | #include "xfs_attr_sf.h" | 33 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
39 | #include "xfs_vfs.h" | ||
40 | #include "xfs_vnode.h" | 35 | #include "xfs_vnode.h" |
41 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
42 | #include "xfs_inode.h" | 37 | #include "xfs_inode.h" |
@@ -44,221 +39,219 @@ | |||
44 | #include "xfs_error.h" | 39 | #include "xfs_error.h" |
45 | #include "xfs_dfrag.h" | 40 | #include "xfs_dfrag.h" |
46 | #include "xfs_vnodeops.h" | 41 | #include "xfs_vnodeops.h" |
42 | #include "xfs_fsops.h" | ||
43 | #include "xfs_alloc.h" | ||
44 | #include "xfs_rtalloc.h" | ||
45 | #include "xfs_attr.h" | ||
46 | #include "xfs_ioctl.h" | ||
47 | #include "xfs_ioctl32.h" | 47 | #include "xfs_ioctl32.h" |
48 | 48 | ||
49 | #define _NATIVE_IOC(cmd, type) \ | 49 | #define _NATIVE_IOC(cmd, type) \ |
50 | _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type)) | 50 | _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type)) |
51 | 51 | ||
52 | #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) | 52 | #ifdef BROKEN_X86_ALIGNMENT |
53 | #define BROKEN_X86_ALIGNMENT | 53 | STATIC int |
54 | #define _PACKED __attribute__((packed)) | 54 | xfs_compat_flock64_copyin( |
55 | /* on ia32 l_start is on a 32-bit boundary */ | 55 | xfs_flock64_t *bf, |
56 | typedef struct xfs_flock64_32 { | 56 | compat_xfs_flock64_t __user *arg32) |
57 | __s16 l_type; | ||
58 | __s16 l_whence; | ||
59 | __s64 l_start __attribute__((packed)); | ||
60 | /* len == 0 means until end of file */ | ||
61 | __s64 l_len __attribute__((packed)); | ||
62 | __s32 l_sysid; | ||
63 | __u32 l_pid; | ||
64 | __s32 l_pad[4]; /* reserve area */ | ||
65 | } xfs_flock64_32_t; | ||
66 | |||
67 | #define XFS_IOC_ALLOCSP_32 _IOW ('X', 10, struct xfs_flock64_32) | ||
68 | #define XFS_IOC_FREESP_32 _IOW ('X', 11, struct xfs_flock64_32) | ||
69 | #define XFS_IOC_ALLOCSP64_32 _IOW ('X', 36, struct xfs_flock64_32) | ||
70 | #define XFS_IOC_FREESP64_32 _IOW ('X', 37, struct xfs_flock64_32) | ||
71 | #define XFS_IOC_RESVSP_32 _IOW ('X', 40, struct xfs_flock64_32) | ||
72 | #define XFS_IOC_UNRESVSP_32 _IOW ('X', 41, struct xfs_flock64_32) | ||
73 | #define XFS_IOC_RESVSP64_32 _IOW ('X', 42, struct xfs_flock64_32) | ||
74 | #define XFS_IOC_UNRESVSP64_32 _IOW ('X', 43, struct xfs_flock64_32) | ||
75 | |||
76 | /* just account for different alignment */ | ||
77 | STATIC unsigned long | ||
78 | xfs_ioctl32_flock( | ||
79 | unsigned long arg) | ||
80 | { | 57 | { |
81 | xfs_flock64_32_t __user *p32 = (void __user *)arg; | 58 | if (get_user(bf->l_type, &arg32->l_type) || |
82 | xfs_flock64_t __user *p = compat_alloc_user_space(sizeof(*p)); | 59 | get_user(bf->l_whence, &arg32->l_whence) || |
83 | 60 | get_user(bf->l_start, &arg32->l_start) || | |
84 | if (copy_in_user(&p->l_type, &p32->l_type, sizeof(s16)) || | 61 | get_user(bf->l_len, &arg32->l_len) || |
85 | copy_in_user(&p->l_whence, &p32->l_whence, sizeof(s16)) || | 62 | get_user(bf->l_sysid, &arg32->l_sysid) || |
86 | copy_in_user(&p->l_start, &p32->l_start, sizeof(s64)) || | 63 | get_user(bf->l_pid, &arg32->l_pid) || |
87 | copy_in_user(&p->l_len, &p32->l_len, sizeof(s64)) || | 64 | copy_from_user(bf->l_pad, &arg32->l_pad, 4*sizeof(u32))) |
88 | copy_in_user(&p->l_sysid, &p32->l_sysid, sizeof(s32)) || | 65 | return -XFS_ERROR(EFAULT); |
89 | copy_in_user(&p->l_pid, &p32->l_pid, sizeof(u32)) || | 66 | return 0; |
90 | copy_in_user(&p->l_pad, &p32->l_pad, 4*sizeof(u32))) | ||
91 | return -EFAULT; | ||
92 | |||
93 | return (unsigned long)p; | ||
94 | } | 67 | } |
95 | 68 | ||
96 | typedef struct compat_xfs_fsop_geom_v1 { | 69 | STATIC int |
97 | __u32 blocksize; /* filesystem (data) block size */ | 70 | xfs_compat_ioc_fsgeometry_v1( |
98 | __u32 rtextsize; /* realtime extent size */ | 71 | struct xfs_mount *mp, |
99 | __u32 agblocks; /* fsblocks in an AG */ | 72 | compat_xfs_fsop_geom_v1_t __user *arg32) |
100 | __u32 agcount; /* number of allocation groups */ | ||
101 | __u32 logblocks; /* fsblocks in the log */ | ||
102 | __u32 sectsize; /* (data) sector size, bytes */ | ||
103 | __u32 inodesize; /* inode size in bytes */ | ||
104 | __u32 imaxpct; /* max allowed inode space(%) */ | ||
105 | __u64 datablocks; /* fsblocks in data subvolume */ | ||
106 | __u64 rtblocks; /* fsblocks in realtime subvol */ | ||
107 | __u64 rtextents; /* rt extents in realtime subvol*/ | ||
108 | __u64 logstart; /* starting fsblock of the log */ | ||
109 | unsigned char uuid[16]; /* unique id of the filesystem */ | ||
110 | __u32 sunit; /* stripe unit, fsblocks */ | ||
111 | __u32 swidth; /* stripe width, fsblocks */ | ||
112 | __s32 version; /* structure version */ | ||
113 | __u32 flags; /* superblock version flags */ | ||
114 | __u32 logsectsize; /* log sector size, bytes */ | ||
115 | __u32 rtsectsize; /* realtime sector size, bytes */ | ||
116 | __u32 dirblocksize; /* directory block size, bytes */ | ||
117 | } __attribute__((packed)) compat_xfs_fsop_geom_v1_t; | ||
118 | |||
119 | #define XFS_IOC_FSGEOMETRY_V1_32 \ | ||
120 | _IOR ('X', 100, struct compat_xfs_fsop_geom_v1) | ||
121 | |||
122 | STATIC unsigned long xfs_ioctl32_geom_v1(unsigned long arg) | ||
123 | { | 73 | { |
124 | compat_xfs_fsop_geom_v1_t __user *p32 = (void __user *)arg; | 74 | xfs_fsop_geom_t fsgeo; |
125 | xfs_fsop_geom_v1_t __user *p = compat_alloc_user_space(sizeof(*p)); | 75 | int error; |
126 | 76 | ||
127 | if (copy_in_user(p, p32, sizeof(*p32))) | 77 | error = xfs_fs_geometry(mp, &fsgeo, 3); |
128 | return -EFAULT; | 78 | if (error) |
129 | return (unsigned long)p; | 79 | return -error; |
80 | /* The 32-bit variant simply has some padding at the end */ | ||
81 | if (copy_to_user(arg32, &fsgeo, sizeof(struct compat_xfs_fsop_geom_v1))) | ||
82 | return -XFS_ERROR(EFAULT); | ||
83 | return 0; | ||
130 | } | 84 | } |
131 | 85 | ||
132 | typedef struct compat_xfs_inogrp { | 86 | STATIC int |
133 | __u64 xi_startino; /* starting inode number */ | 87 | xfs_compat_growfs_data_copyin( |
134 | __s32 xi_alloccount; /* # bits set in allocmask */ | 88 | struct xfs_growfs_data *in, |
135 | __u64 xi_allocmask; /* mask of allocated inodes */ | 89 | compat_xfs_growfs_data_t __user *arg32) |
136 | } __attribute__((packed)) compat_xfs_inogrp_t; | ||
137 | |||
138 | STATIC int xfs_inumbers_fmt_compat( | ||
139 | void __user *ubuffer, | ||
140 | const xfs_inogrp_t *buffer, | ||
141 | long count, | ||
142 | long *written) | ||
143 | { | 90 | { |
144 | compat_xfs_inogrp_t __user *p32 = ubuffer; | 91 | if (get_user(in->newblocks, &arg32->newblocks) || |
145 | long i; | 92 | get_user(in->imaxpct, &arg32->imaxpct)) |
93 | return -XFS_ERROR(EFAULT); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | STATIC int | ||
98 | xfs_compat_growfs_rt_copyin( | ||
99 | struct xfs_growfs_rt *in, | ||
100 | compat_xfs_growfs_rt_t __user *arg32) | ||
101 | { | ||
102 | if (get_user(in->newblocks, &arg32->newblocks) || | ||
103 | get_user(in->extsize, &arg32->extsize)) | ||
104 | return -XFS_ERROR(EFAULT); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | STATIC int | ||
109 | xfs_inumbers_fmt_compat( | ||
110 | void __user *ubuffer, | ||
111 | const xfs_inogrp_t *buffer, | ||
112 | long count, | ||
113 | long *written) | ||
114 | { | ||
115 | compat_xfs_inogrp_t __user *p32 = ubuffer; | ||
116 | long i; | ||
146 | 117 | ||
147 | for (i = 0; i < count; i++) { | 118 | for (i = 0; i < count; i++) { |
148 | if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) || | 119 | if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) || |
149 | put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) || | 120 | put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) || |
150 | put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask)) | 121 | put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask)) |
151 | return -EFAULT; | 122 | return -XFS_ERROR(EFAULT); |
152 | } | 123 | } |
153 | *written = count * sizeof(*p32); | 124 | *written = count * sizeof(*p32); |
154 | return 0; | 125 | return 0; |
155 | } | 126 | } |
156 | 127 | ||
157 | #else | 128 | #else |
158 | |||
159 | #define xfs_inumbers_fmt_compat xfs_inumbers_fmt | 129 | #define xfs_inumbers_fmt_compat xfs_inumbers_fmt |
160 | #define _PACKED | 130 | #endif /* BROKEN_X86_ALIGNMENT */ |
161 | 131 | ||
162 | #endif | 132 | STATIC int |
133 | xfs_ioctl32_bstime_copyin( | ||
134 | xfs_bstime_t *bstime, | ||
135 | compat_xfs_bstime_t __user *bstime32) | ||
136 | { | ||
137 | compat_time_t sec32; /* tv_sec differs on 64 vs. 32 */ | ||
163 | 138 | ||
164 | /* XFS_IOC_FSBULKSTAT and friends */ | 139 | if (get_user(sec32, &bstime32->tv_sec) || |
140 | get_user(bstime->tv_nsec, &bstime32->tv_nsec)) | ||
141 | return -XFS_ERROR(EFAULT); | ||
142 | bstime->tv_sec = sec32; | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | /* xfs_bstat_t has differing alignment on intel, & bstime_t sizes everywhere */ | ||
147 | STATIC int | ||
148 | xfs_ioctl32_bstat_copyin( | ||
149 | xfs_bstat_t *bstat, | ||
150 | compat_xfs_bstat_t __user *bstat32) | ||
151 | { | ||
152 | if (get_user(bstat->bs_ino, &bstat32->bs_ino) || | ||
153 | get_user(bstat->bs_mode, &bstat32->bs_mode) || | ||
154 | get_user(bstat->bs_nlink, &bstat32->bs_nlink) || | ||
155 | get_user(bstat->bs_uid, &bstat32->bs_uid) || | ||
156 | get_user(bstat->bs_gid, &bstat32->bs_gid) || | ||
157 | get_user(bstat->bs_rdev, &bstat32->bs_rdev) || | ||
158 | get_user(bstat->bs_blksize, &bstat32->bs_blksize) || | ||
159 | get_user(bstat->bs_size, &bstat32->bs_size) || | ||
160 | xfs_ioctl32_bstime_copyin(&bstat->bs_atime, &bstat32->bs_atime) || | ||
161 | xfs_ioctl32_bstime_copyin(&bstat->bs_mtime, &bstat32->bs_mtime) || | ||
162 | xfs_ioctl32_bstime_copyin(&bstat->bs_ctime, &bstat32->bs_ctime) || | ||
163 | get_user(bstat->bs_blocks, &bstat32->bs_size) || | ||
164 | get_user(bstat->bs_xflags, &bstat32->bs_size) || | ||
165 | get_user(bstat->bs_extsize, &bstat32->bs_extsize) || | ||
166 | get_user(bstat->bs_extents, &bstat32->bs_extents) || | ||
167 | get_user(bstat->bs_gen, &bstat32->bs_gen) || | ||
168 | get_user(bstat->bs_projid, &bstat32->bs_projid) || | ||
169 | get_user(bstat->bs_dmevmask, &bstat32->bs_dmevmask) || | ||
170 | get_user(bstat->bs_dmstate, &bstat32->bs_dmstate) || | ||
171 | get_user(bstat->bs_aextents, &bstat32->bs_aextents)) | ||
172 | return -XFS_ERROR(EFAULT); | ||
173 | return 0; | ||
174 | } | ||
165 | 175 | ||
166 | typedef struct compat_xfs_bstime { | 176 | /* XFS_IOC_FSBULKSTAT and friends */ |
167 | __s32 tv_sec; /* seconds */ | ||
168 | __s32 tv_nsec; /* and nanoseconds */ | ||
169 | } compat_xfs_bstime_t; | ||
170 | 177 | ||
171 | STATIC int xfs_bstime_store_compat( | 178 | STATIC int |
172 | compat_xfs_bstime_t __user *p32, | 179 | xfs_bstime_store_compat( |
173 | const xfs_bstime_t *p) | 180 | compat_xfs_bstime_t __user *p32, |
181 | const xfs_bstime_t *p) | ||
174 | { | 182 | { |
175 | __s32 sec32; | 183 | __s32 sec32; |
176 | 184 | ||
177 | sec32 = p->tv_sec; | 185 | sec32 = p->tv_sec; |
178 | if (put_user(sec32, &p32->tv_sec) || | 186 | if (put_user(sec32, &p32->tv_sec) || |
179 | put_user(p->tv_nsec, &p32->tv_nsec)) | 187 | put_user(p->tv_nsec, &p32->tv_nsec)) |
180 | return -EFAULT; | 188 | return -XFS_ERROR(EFAULT); |
181 | return 0; | 189 | return 0; |
182 | } | 190 | } |
183 | 191 | ||
184 | typedef struct compat_xfs_bstat { | 192 | /* Return 0 on success or positive error (to xfs_bulkstat()) */ |
185 | __u64 bs_ino; /* inode number */ | 193 | STATIC int |
186 | __u16 bs_mode; /* type and mode */ | 194 | xfs_bulkstat_one_fmt_compat( |
187 | __u16 bs_nlink; /* number of links */ | ||
188 | __u32 bs_uid; /* user id */ | ||
189 | __u32 bs_gid; /* group id */ | ||
190 | __u32 bs_rdev; /* device value */ | ||
191 | __s32 bs_blksize; /* block size */ | ||
192 | __s64 bs_size; /* file size */ | ||
193 | compat_xfs_bstime_t bs_atime; /* access time */ | ||
194 | compat_xfs_bstime_t bs_mtime; /* modify time */ | ||
195 | compat_xfs_bstime_t bs_ctime; /* inode change time */ | ||
196 | int64_t bs_blocks; /* number of blocks */ | ||
197 | __u32 bs_xflags; /* extended flags */ | ||
198 | __s32 bs_extsize; /* extent size */ | ||
199 | __s32 bs_extents; /* number of extents */ | ||
200 | __u32 bs_gen; /* generation count */ | ||
201 | __u16 bs_projid; /* project id */ | ||
202 | unsigned char bs_pad[14]; /* pad space, unused */ | ||
203 | __u32 bs_dmevmask; /* DMIG event mask */ | ||
204 | __u16 bs_dmstate; /* DMIG state info */ | ||
205 | __u16 bs_aextents; /* attribute number of extents */ | ||
206 | } _PACKED compat_xfs_bstat_t; | ||
207 | |||
208 | STATIC int xfs_bulkstat_one_fmt_compat( | ||
209 | void __user *ubuffer, | 195 | void __user *ubuffer, |
196 | int ubsize, | ||
197 | int *ubused, | ||
210 | const xfs_bstat_t *buffer) | 198 | const xfs_bstat_t *buffer) |
211 | { | 199 | { |
212 | compat_xfs_bstat_t __user *p32 = ubuffer; | 200 | compat_xfs_bstat_t __user *p32 = ubuffer; |
213 | 201 | ||
214 | if (put_user(buffer->bs_ino, &p32->bs_ino) || | 202 | if (ubsize < sizeof(*p32)) |
215 | put_user(buffer->bs_mode, &p32->bs_mode) || | 203 | return XFS_ERROR(ENOMEM); |
216 | put_user(buffer->bs_nlink, &p32->bs_nlink) || | 204 | |
217 | put_user(buffer->bs_uid, &p32->bs_uid) || | 205 | if (put_user(buffer->bs_ino, &p32->bs_ino) || |
218 | put_user(buffer->bs_gid, &p32->bs_gid) || | 206 | put_user(buffer->bs_mode, &p32->bs_mode) || |
219 | put_user(buffer->bs_rdev, &p32->bs_rdev) || | 207 | put_user(buffer->bs_nlink, &p32->bs_nlink) || |
220 | put_user(buffer->bs_blksize, &p32->bs_blksize) || | 208 | put_user(buffer->bs_uid, &p32->bs_uid) || |
221 | put_user(buffer->bs_size, &p32->bs_size) || | 209 | put_user(buffer->bs_gid, &p32->bs_gid) || |
210 | put_user(buffer->bs_rdev, &p32->bs_rdev) || | ||
211 | put_user(buffer->bs_blksize, &p32->bs_blksize) || | ||
212 | put_user(buffer->bs_size, &p32->bs_size) || | ||
222 | xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) || | 213 | xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) || |
223 | xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) || | 214 | xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) || |
224 | xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) || | 215 | xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) || |
225 | put_user(buffer->bs_blocks, &p32->bs_blocks) || | 216 | put_user(buffer->bs_blocks, &p32->bs_blocks) || |
226 | put_user(buffer->bs_xflags, &p32->bs_xflags) || | 217 | put_user(buffer->bs_xflags, &p32->bs_xflags) || |
227 | put_user(buffer->bs_extsize, &p32->bs_extsize) || | 218 | put_user(buffer->bs_extsize, &p32->bs_extsize) || |
228 | put_user(buffer->bs_extents, &p32->bs_extents) || | 219 | put_user(buffer->bs_extents, &p32->bs_extents) || |
229 | put_user(buffer->bs_gen, &p32->bs_gen) || | 220 | put_user(buffer->bs_gen, &p32->bs_gen) || |
230 | put_user(buffer->bs_projid, &p32->bs_projid) || | 221 | put_user(buffer->bs_projid, &p32->bs_projid) || |
231 | put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) || | 222 | put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) || |
232 | put_user(buffer->bs_dmstate, &p32->bs_dmstate) || | 223 | put_user(buffer->bs_dmstate, &p32->bs_dmstate) || |
233 | put_user(buffer->bs_aextents, &p32->bs_aextents)) | 224 | put_user(buffer->bs_aextents, &p32->bs_aextents)) |
234 | return -EFAULT; | 225 | return XFS_ERROR(EFAULT); |
235 | return sizeof(*p32); | 226 | if (ubused) |
227 | *ubused = sizeof(*p32); | ||
228 | return 0; | ||
236 | } | 229 | } |
237 | 230 | ||
238 | 231 | STATIC int | |
239 | 232 | xfs_bulkstat_one_compat( | |
240 | typedef struct compat_xfs_fsop_bulkreq { | 233 | xfs_mount_t *mp, /* mount point for filesystem */ |
241 | compat_uptr_t lastip; /* last inode # pointer */ | 234 | xfs_ino_t ino, /* inode number to get data for */ |
242 | __s32 icount; /* count of entries in buffer */ | 235 | void __user *buffer, /* buffer to place output in */ |
243 | compat_uptr_t ubuffer; /* user buffer for inode desc. */ | 236 | int ubsize, /* size of buffer */ |
244 | compat_uptr_t ocount; /* output count pointer */ | 237 | void *private_data, /* my private data */ |
245 | } compat_xfs_fsop_bulkreq_t; | 238 | xfs_daddr_t bno, /* starting bno of inode cluster */ |
246 | 239 | int *ubused, /* bytes used by me */ | |
247 | #define XFS_IOC_FSBULKSTAT_32 \ | 240 | void *dibuff, /* on-disk inode buffer */ |
248 | _IOWR('X', 101, struct compat_xfs_fsop_bulkreq) | 241 | int *stat) /* BULKSTAT_RV_... */ |
249 | #define XFS_IOC_FSBULKSTAT_SINGLE_32 \ | 242 | { |
250 | _IOWR('X', 102, struct compat_xfs_fsop_bulkreq) | 243 | return xfs_bulkstat_one_int(mp, ino, buffer, ubsize, |
251 | #define XFS_IOC_FSINUMBERS_32 \ | 244 | xfs_bulkstat_one_fmt_compat, bno, |
252 | _IOWR('X', 103, struct compat_xfs_fsop_bulkreq) | 245 | ubused, dibuff, stat); |
246 | } | ||
253 | 247 | ||
254 | /* copied from xfs_ioctl.c */ | 248 | /* copied from xfs_ioctl.c */ |
255 | STATIC int | 249 | STATIC int |
256 | xfs_ioc_bulkstat_compat( | 250 | xfs_compat_ioc_bulkstat( |
257 | xfs_mount_t *mp, | 251 | xfs_mount_t *mp, |
258 | unsigned int cmd, | 252 | unsigned int cmd, |
259 | void __user *arg) | 253 | compat_xfs_fsop_bulkreq_t __user *p32) |
260 | { | 254 | { |
261 | compat_xfs_fsop_bulkreq_t __user *p32 = (void __user *)arg; | ||
262 | u32 addr; | 255 | u32 addr; |
263 | xfs_fsop_bulkreq_t bulkreq; | 256 | xfs_fsop_bulkreq_t bulkreq; |
264 | int count; /* # of records returned */ | 257 | int count; /* # of records returned */ |
@@ -270,20 +263,20 @@ xfs_ioc_bulkstat_compat( | |||
270 | /* should be called again (unused here, but used in dmapi) */ | 263 | /* should be called again (unused here, but used in dmapi) */ |
271 | 264 | ||
272 | if (!capable(CAP_SYS_ADMIN)) | 265 | if (!capable(CAP_SYS_ADMIN)) |
273 | return -EPERM; | 266 | return -XFS_ERROR(EPERM); |
274 | 267 | ||
275 | if (XFS_FORCED_SHUTDOWN(mp)) | 268 | if (XFS_FORCED_SHUTDOWN(mp)) |
276 | return -XFS_ERROR(EIO); | 269 | return -XFS_ERROR(EIO); |
277 | 270 | ||
278 | if (get_user(addr, &p32->lastip)) | 271 | if (get_user(addr, &p32->lastip)) |
279 | return -EFAULT; | 272 | return -XFS_ERROR(EFAULT); |
280 | bulkreq.lastip = compat_ptr(addr); | 273 | bulkreq.lastip = compat_ptr(addr); |
281 | if (get_user(bulkreq.icount, &p32->icount) || | 274 | if (get_user(bulkreq.icount, &p32->icount) || |
282 | get_user(addr, &p32->ubuffer)) | 275 | get_user(addr, &p32->ubuffer)) |
283 | return -EFAULT; | 276 | return -XFS_ERROR(EFAULT); |
284 | bulkreq.ubuffer = compat_ptr(addr); | 277 | bulkreq.ubuffer = compat_ptr(addr); |
285 | if (get_user(addr, &p32->ocount)) | 278 | if (get_user(addr, &p32->ocount)) |
286 | return -EFAULT; | 279 | return -XFS_ERROR(EFAULT); |
287 | bulkreq.ocount = compat_ptr(addr); | 280 | bulkreq.ocount = compat_ptr(addr); |
288 | 281 | ||
289 | if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64))) | 282 | if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64))) |
@@ -295,17 +288,22 @@ xfs_ioc_bulkstat_compat( | |||
295 | if (bulkreq.ubuffer == NULL) | 288 | if (bulkreq.ubuffer == NULL) |
296 | return -XFS_ERROR(EINVAL); | 289 | return -XFS_ERROR(EINVAL); |
297 | 290 | ||
298 | if (cmd == XFS_IOC_FSINUMBERS) | 291 | if (cmd == XFS_IOC_FSINUMBERS_32) { |
299 | error = xfs_inumbers(mp, &inlast, &count, | 292 | error = xfs_inumbers(mp, &inlast, &count, |
300 | bulkreq.ubuffer, xfs_inumbers_fmt_compat); | 293 | bulkreq.ubuffer, xfs_inumbers_fmt_compat); |
301 | else { | 294 | } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) { |
302 | /* declare a var to get a warning in case the type changes */ | 295 | int res; |
303 | bulkstat_one_fmt_pf formatter = xfs_bulkstat_one_fmt_compat; | 296 | |
297 | error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer, | ||
298 | sizeof(compat_xfs_bstat_t), | ||
299 | NULL, 0, NULL, NULL, &res); | ||
300 | } else if (cmd == XFS_IOC_FSBULKSTAT_32) { | ||
304 | error = xfs_bulkstat(mp, &inlast, &count, | 301 | error = xfs_bulkstat(mp, &inlast, &count, |
305 | xfs_bulkstat_one, formatter, | 302 | xfs_bulkstat_one_compat, NULL, |
306 | sizeof(compat_xfs_bstat_t), bulkreq.ubuffer, | 303 | sizeof(compat_xfs_bstat_t), bulkreq.ubuffer, |
307 | BULKSTAT_FG_QUICK, &done); | 304 | BULKSTAT_FG_QUICK, &done); |
308 | } | 305 | } else |
306 | error = XFS_ERROR(EINVAL); | ||
309 | if (error) | 307 | if (error) |
310 | return -error; | 308 | return -error; |
311 | 309 | ||
@@ -321,63 +319,306 @@ xfs_ioc_bulkstat_compat( | |||
321 | return 0; | 319 | return 0; |
322 | } | 320 | } |
323 | 321 | ||
322 | STATIC int | ||
323 | xfs_compat_handlereq_copyin( | ||
324 | xfs_fsop_handlereq_t *hreq, | ||
325 | compat_xfs_fsop_handlereq_t __user *arg32) | ||
326 | { | ||
327 | compat_xfs_fsop_handlereq_t hreq32; | ||
328 | |||
329 | if (copy_from_user(&hreq32, arg32, sizeof(compat_xfs_fsop_handlereq_t))) | ||
330 | return -XFS_ERROR(EFAULT); | ||
331 | |||
332 | hreq->fd = hreq32.fd; | ||
333 | hreq->path = compat_ptr(hreq32.path); | ||
334 | hreq->oflags = hreq32.oflags; | ||
335 | hreq->ihandle = compat_ptr(hreq32.ihandle); | ||
336 | hreq->ihandlen = hreq32.ihandlen; | ||
337 | hreq->ohandle = compat_ptr(hreq32.ohandle); | ||
338 | hreq->ohandlen = compat_ptr(hreq32.ohandlen); | ||
324 | 339 | ||
340 | return 0; | ||
341 | } | ||
325 | 342 | ||
326 | typedef struct compat_xfs_fsop_handlereq { | 343 | /* |
327 | __u32 fd; /* fd for FD_TO_HANDLE */ | 344 | * Convert userspace handle data into inode. |
328 | compat_uptr_t path; /* user pathname */ | 345 | * |
329 | __u32 oflags; /* open flags */ | 346 | * We use the fact that all the fsop_handlereq ioctl calls have a data |
330 | compat_uptr_t ihandle; /* user supplied handle */ | 347 | * structure argument whose first component is always a xfs_fsop_handlereq_t, |
331 | __u32 ihandlen; /* user supplied length */ | 348 | * so we can pass that sub structure into this handy, shared routine. |
332 | compat_uptr_t ohandle; /* user buffer for handle */ | 349 | * |
333 | compat_uptr_t ohandlen; /* user buffer length */ | 350 | * If no error, caller must always iput the returned inode. |
334 | } compat_xfs_fsop_handlereq_t; | 351 | */ |
335 | 352 | STATIC int | |
336 | #define XFS_IOC_PATH_TO_FSHANDLE_32 \ | 353 | xfs_vget_fsop_handlereq_compat( |
337 | _IOWR('X', 104, struct compat_xfs_fsop_handlereq) | 354 | xfs_mount_t *mp, |
338 | #define XFS_IOC_PATH_TO_HANDLE_32 \ | 355 | struct inode *parinode, /* parent inode pointer */ |
339 | _IOWR('X', 105, struct compat_xfs_fsop_handlereq) | 356 | compat_xfs_fsop_handlereq_t *hreq, |
340 | #define XFS_IOC_FD_TO_HANDLE_32 \ | 357 | struct inode **inode) |
341 | _IOWR('X', 106, struct compat_xfs_fsop_handlereq) | ||
342 | #define XFS_IOC_OPEN_BY_HANDLE_32 \ | ||
343 | _IOWR('X', 107, struct compat_xfs_fsop_handlereq) | ||
344 | #define XFS_IOC_READLINK_BY_HANDLE_32 \ | ||
345 | _IOWR('X', 108, struct compat_xfs_fsop_handlereq) | ||
346 | |||
347 | STATIC unsigned long xfs_ioctl32_fshandle(unsigned long arg) | ||
348 | { | 358 | { |
349 | compat_xfs_fsop_handlereq_t __user *p32 = (void __user *)arg; | 359 | void __user *hanp; |
350 | xfs_fsop_handlereq_t __user *p = compat_alloc_user_space(sizeof(*p)); | 360 | size_t hlen; |
351 | u32 addr; | 361 | xfs_fid_t *xfid; |
352 | 362 | xfs_handle_t *handlep; | |
353 | if (copy_in_user(&p->fd, &p32->fd, sizeof(__u32)) || | 363 | xfs_handle_t handle; |
354 | get_user(addr, &p32->path) || | 364 | xfs_inode_t *ip; |
355 | put_user(compat_ptr(addr), &p->path) || | 365 | xfs_ino_t ino; |
356 | copy_in_user(&p->oflags, &p32->oflags, sizeof(__u32)) || | 366 | __u32 igen; |
357 | get_user(addr, &p32->ihandle) || | 367 | int error; |
358 | put_user(compat_ptr(addr), &p->ihandle) || | 368 | |
359 | copy_in_user(&p->ihandlen, &p32->ihandlen, sizeof(__u32)) || | 369 | /* |
360 | get_user(addr, &p32->ohandle) || | 370 | * Only allow handle opens under a directory. |
361 | put_user(compat_ptr(addr), &p->ohandle) || | 371 | */ |
362 | get_user(addr, &p32->ohandlen) || | 372 | if (!S_ISDIR(parinode->i_mode)) |
363 | put_user(compat_ptr(addr), &p->ohandlen)) | 373 | return XFS_ERROR(ENOTDIR); |
364 | return -EFAULT; | 374 | |
365 | 375 | hanp = compat_ptr(hreq->ihandle); | |
366 | return (unsigned long)p; | 376 | hlen = hreq->ihandlen; |
377 | handlep = &handle; | ||
378 | |||
379 | if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep)) | ||
380 | return XFS_ERROR(EINVAL); | ||
381 | if (copy_from_user(handlep, hanp, hlen)) | ||
382 | return XFS_ERROR(EFAULT); | ||
383 | if (hlen < sizeof(*handlep)) | ||
384 | memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen); | ||
385 | if (hlen > sizeof(handlep->ha_fsid)) { | ||
386 | if (handlep->ha_fid.fid_len != | ||
387 | (hlen - sizeof(handlep->ha_fsid) - | ||
388 | sizeof(handlep->ha_fid.fid_len)) || | ||
389 | handlep->ha_fid.fid_pad) | ||
390 | return XFS_ERROR(EINVAL); | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * Crack the handle, obtain the inode # & generation # | ||
395 | */ | ||
396 | xfid = (struct xfs_fid *)&handlep->ha_fid; | ||
397 | if (xfid->fid_len == sizeof(*xfid) - sizeof(xfid->fid_len)) { | ||
398 | ino = xfid->fid_ino; | ||
399 | igen = xfid->fid_gen; | ||
400 | } else { | ||
401 | return XFS_ERROR(EINVAL); | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * Get the XFS inode, building a Linux inode to go with it. | ||
406 | */ | ||
407 | error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0); | ||
408 | if (error) | ||
409 | return error; | ||
410 | if (ip == NULL) | ||
411 | return XFS_ERROR(EIO); | ||
412 | if (ip->i_d.di_gen != igen) { | ||
413 | xfs_iput_new(ip, XFS_ILOCK_SHARED); | ||
414 | return XFS_ERROR(ENOENT); | ||
415 | } | ||
416 | |||
417 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
418 | |||
419 | *inode = VFS_I(ip); | ||
420 | return 0; | ||
367 | } | 421 | } |
368 | 422 | ||
423 | STATIC int | ||
424 | xfs_compat_attrlist_by_handle( | ||
425 | xfs_mount_t *mp, | ||
426 | void __user *arg, | ||
427 | struct inode *parinode) | ||
428 | { | ||
429 | int error; | ||
430 | attrlist_cursor_kern_t *cursor; | ||
431 | compat_xfs_fsop_attrlist_handlereq_t al_hreq; | ||
432 | struct inode *inode; | ||
433 | char *kbuf; | ||
434 | |||
435 | if (!capable(CAP_SYS_ADMIN)) | ||
436 | return -XFS_ERROR(EPERM); | ||
437 | if (copy_from_user(&al_hreq, arg, | ||
438 | sizeof(compat_xfs_fsop_attrlist_handlereq_t))) | ||
439 | return -XFS_ERROR(EFAULT); | ||
440 | if (al_hreq.buflen > XATTR_LIST_MAX) | ||
441 | return -XFS_ERROR(EINVAL); | ||
442 | |||
443 | /* | ||
444 | * Reject flags, only allow namespaces. | ||
445 | */ | ||
446 | if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE)) | ||
447 | return -XFS_ERROR(EINVAL); | ||
448 | |||
449 | error = xfs_vget_fsop_handlereq_compat(mp, parinode, &al_hreq.hreq, | ||
450 | &inode); | ||
451 | if (error) | ||
452 | goto out; | ||
453 | |||
454 | kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL); | ||
455 | if (!kbuf) | ||
456 | goto out_vn_rele; | ||
457 | |||
458 | cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; | ||
459 | error = xfs_attr_list(XFS_I(inode), kbuf, al_hreq.buflen, | ||
460 | al_hreq.flags, cursor); | ||
461 | if (error) | ||
462 | goto out_kfree; | ||
463 | |||
464 | if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen)) | ||
465 | error = -EFAULT; | ||
466 | |||
467 | out_kfree: | ||
468 | kfree(kbuf); | ||
469 | out_vn_rele: | ||
470 | iput(inode); | ||
471 | out: | ||
472 | return -error; | ||
473 | } | ||
369 | 474 | ||
370 | STATIC long | 475 | STATIC int |
371 | xfs_compat_ioctl( | 476 | xfs_compat_attrmulti_by_handle( |
372 | int mode, | 477 | xfs_mount_t *mp, |
373 | struct file *file, | 478 | void __user *arg, |
374 | unsigned cmd, | 479 | struct inode *parinode) |
375 | unsigned long arg) | 480 | { |
481 | int error; | ||
482 | compat_xfs_attr_multiop_t *ops; | ||
483 | compat_xfs_fsop_attrmulti_handlereq_t am_hreq; | ||
484 | struct inode *inode; | ||
485 | unsigned int i, size; | ||
486 | char *attr_name; | ||
487 | |||
488 | if (!capable(CAP_SYS_ADMIN)) | ||
489 | return -XFS_ERROR(EPERM); | ||
490 | if (copy_from_user(&am_hreq, arg, | ||
491 | sizeof(compat_xfs_fsop_attrmulti_handlereq_t))) | ||
492 | return -XFS_ERROR(EFAULT); | ||
493 | |||
494 | error = xfs_vget_fsop_handlereq_compat(mp, parinode, &am_hreq.hreq, | ||
495 | &inode); | ||
496 | if (error) | ||
497 | goto out; | ||
498 | |||
499 | error = E2BIG; | ||
500 | size = am_hreq.opcount * sizeof(compat_xfs_attr_multiop_t); | ||
501 | if (!size || size > 16 * PAGE_SIZE) | ||
502 | goto out_vn_rele; | ||
503 | |||
504 | error = ENOMEM; | ||
505 | ops = kmalloc(size, GFP_KERNEL); | ||
506 | if (!ops) | ||
507 | goto out_vn_rele; | ||
508 | |||
509 | error = EFAULT; | ||
510 | if (copy_from_user(ops, compat_ptr(am_hreq.ops), size)) | ||
511 | goto out_kfree_ops; | ||
512 | |||
513 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); | ||
514 | if (!attr_name) | ||
515 | goto out_kfree_ops; | ||
516 | |||
517 | |||
518 | error = 0; | ||
519 | for (i = 0; i < am_hreq.opcount; i++) { | ||
520 | ops[i].am_error = strncpy_from_user(attr_name, | ||
521 | compat_ptr(ops[i].am_attrname), | ||
522 | MAXNAMELEN); | ||
523 | if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN) | ||
524 | error = -ERANGE; | ||
525 | if (ops[i].am_error < 0) | ||
526 | break; | ||
527 | |||
528 | switch (ops[i].am_opcode) { | ||
529 | case ATTR_OP_GET: | ||
530 | ops[i].am_error = xfs_attrmulti_attr_get(inode, | ||
531 | attr_name, | ||
532 | compat_ptr(ops[i].am_attrvalue), | ||
533 | &ops[i].am_length, ops[i].am_flags); | ||
534 | break; | ||
535 | case ATTR_OP_SET: | ||
536 | ops[i].am_error = xfs_attrmulti_attr_set(inode, | ||
537 | attr_name, | ||
538 | compat_ptr(ops[i].am_attrvalue), | ||
539 | ops[i].am_length, ops[i].am_flags); | ||
540 | break; | ||
541 | case ATTR_OP_REMOVE: | ||
542 | ops[i].am_error = xfs_attrmulti_attr_remove(inode, | ||
543 | attr_name, ops[i].am_flags); | ||
544 | break; | ||
545 | default: | ||
546 | ops[i].am_error = EINVAL; | ||
547 | } | ||
548 | } | ||
549 | |||
550 | if (copy_to_user(compat_ptr(am_hreq.ops), ops, size)) | ||
551 | error = XFS_ERROR(EFAULT); | ||
552 | |||
553 | kfree(attr_name); | ||
554 | out_kfree_ops: | ||
555 | kfree(ops); | ||
556 | out_vn_rele: | ||
557 | iput(inode); | ||
558 | out: | ||
559 | return -error; | ||
560 | } | ||
561 | |||
562 | STATIC int | ||
563 | xfs_compat_fssetdm_by_handle( | ||
564 | xfs_mount_t *mp, | ||
565 | void __user *arg, | ||
566 | struct inode *parinode) | ||
567 | { | ||
568 | int error; | ||
569 | struct fsdmidata fsd; | ||
570 | compat_xfs_fsop_setdm_handlereq_t dmhreq; | ||
571 | struct inode *inode; | ||
572 | |||
573 | if (!capable(CAP_MKNOD)) | ||
574 | return -XFS_ERROR(EPERM); | ||
575 | if (copy_from_user(&dmhreq, arg, | ||
576 | sizeof(compat_xfs_fsop_setdm_handlereq_t))) | ||
577 | return -XFS_ERROR(EFAULT); | ||
578 | |||
579 | error = xfs_vget_fsop_handlereq_compat(mp, parinode, &dmhreq.hreq, | ||
580 | &inode); | ||
581 | if (error) | ||
582 | return -error; | ||
583 | |||
584 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { | ||
585 | error = -XFS_ERROR(EPERM); | ||
586 | goto out; | ||
587 | } | ||
588 | |||
589 | if (copy_from_user(&fsd, compat_ptr(dmhreq.data), sizeof(fsd))) { | ||
590 | error = -XFS_ERROR(EFAULT); | ||
591 | goto out; | ||
592 | } | ||
593 | |||
594 | error = -xfs_set_dmattrs(XFS_I(inode), fsd.fsd_dmevmask, | ||
595 | fsd.fsd_dmstate); | ||
596 | |||
597 | out: | ||
598 | iput(inode); | ||
599 | return error; | ||
600 | } | ||
601 | |||
602 | long | ||
603 | xfs_file_compat_ioctl( | ||
604 | struct file *filp, | ||
605 | unsigned cmd, | ||
606 | unsigned long p) | ||
376 | { | 607 | { |
377 | struct inode *inode = file->f_path.dentry->d_inode; | 608 | struct inode *inode = filp->f_path.dentry->d_inode; |
378 | int error; | 609 | struct xfs_inode *ip = XFS_I(inode); |
610 | struct xfs_mount *mp = ip->i_mount; | ||
611 | void __user *arg = (void __user *)p; | ||
612 | int ioflags = 0; | ||
613 | int error; | ||
614 | |||
615 | if (filp->f_mode & FMODE_NOCMTIME) | ||
616 | ioflags |= IO_INVIS; | ||
617 | |||
618 | xfs_itrace_entry(ip); | ||
379 | 619 | ||
380 | switch (cmd) { | 620 | switch (cmd) { |
621 | /* No size or alignment issues on any arch */ | ||
381 | case XFS_IOC_DIOINFO: | 622 | case XFS_IOC_DIOINFO: |
382 | case XFS_IOC_FSGEOMETRY: | 623 | case XFS_IOC_FSGEOMETRY: |
383 | case XFS_IOC_FSGETXATTR: | 624 | case XFS_IOC_FSGETXATTR: |
@@ -387,48 +628,18 @@ xfs_compat_ioctl( | |||
387 | case XFS_IOC_GETBMAP: | 628 | case XFS_IOC_GETBMAP: |
388 | case XFS_IOC_GETBMAPA: | 629 | case XFS_IOC_GETBMAPA: |
389 | case XFS_IOC_GETBMAPX: | 630 | case XFS_IOC_GETBMAPX: |
390 | /* not handled | ||
391 | case XFS_IOC_FSSETDM_BY_HANDLE: | ||
392 | case XFS_IOC_ATTRLIST_BY_HANDLE: | ||
393 | case XFS_IOC_ATTRMULTI_BY_HANDLE: | ||
394 | */ | ||
395 | case XFS_IOC_FSCOUNTS: | 631 | case XFS_IOC_FSCOUNTS: |
396 | case XFS_IOC_SET_RESBLKS: | 632 | case XFS_IOC_SET_RESBLKS: |
397 | case XFS_IOC_GET_RESBLKS: | 633 | case XFS_IOC_GET_RESBLKS: |
398 | case XFS_IOC_FSGROWFSDATA: | ||
399 | case XFS_IOC_FSGROWFSLOG: | 634 | case XFS_IOC_FSGROWFSLOG: |
400 | case XFS_IOC_FSGROWFSRT: | ||
401 | case XFS_IOC_FREEZE: | 635 | case XFS_IOC_FREEZE: |
402 | case XFS_IOC_THAW: | 636 | case XFS_IOC_THAW: |
403 | case XFS_IOC_GOINGDOWN: | 637 | case XFS_IOC_GOINGDOWN: |
404 | case XFS_IOC_ERROR_INJECTION: | 638 | case XFS_IOC_ERROR_INJECTION: |
405 | case XFS_IOC_ERROR_CLEARALL: | 639 | case XFS_IOC_ERROR_CLEARALL: |
406 | break; | 640 | return xfs_file_ioctl(filp, cmd, p); |
407 | 641 | #ifndef BROKEN_X86_ALIGNMENT | |
408 | case XFS_IOC32_GETXFLAGS: | 642 | /* These are handled fine if no alignment issues */ |
409 | case XFS_IOC32_SETXFLAGS: | ||
410 | case XFS_IOC32_GETVERSION: | ||
411 | cmd = _NATIVE_IOC(cmd, long); | ||
412 | break; | ||
413 | #ifdef BROKEN_X86_ALIGNMENT | ||
414 | /* xfs_flock_t has wrong u32 vs u64 alignment */ | ||
415 | case XFS_IOC_ALLOCSP_32: | ||
416 | case XFS_IOC_FREESP_32: | ||
417 | case XFS_IOC_ALLOCSP64_32: | ||
418 | case XFS_IOC_FREESP64_32: | ||
419 | case XFS_IOC_RESVSP_32: | ||
420 | case XFS_IOC_UNRESVSP_32: | ||
421 | case XFS_IOC_RESVSP64_32: | ||
422 | case XFS_IOC_UNRESVSP64_32: | ||
423 | arg = xfs_ioctl32_flock(arg); | ||
424 | cmd = _NATIVE_IOC(cmd, struct xfs_flock64); | ||
425 | break; | ||
426 | case XFS_IOC_FSGEOMETRY_V1_32: | ||
427 | arg = xfs_ioctl32_geom_v1(arg); | ||
428 | cmd = _NATIVE_IOC(cmd, struct xfs_fsop_geom_v1); | ||
429 | break; | ||
430 | |||
431 | #else /* These are handled fine if no alignment issues */ | ||
432 | case XFS_IOC_ALLOCSP: | 643 | case XFS_IOC_ALLOCSP: |
433 | case XFS_IOC_FREESP: | 644 | case XFS_IOC_FREESP: |
434 | case XFS_IOC_RESVSP: | 645 | case XFS_IOC_RESVSP: |
@@ -438,51 +649,97 @@ xfs_compat_ioctl( | |||
438 | case XFS_IOC_RESVSP64: | 649 | case XFS_IOC_RESVSP64: |
439 | case XFS_IOC_UNRESVSP64: | 650 | case XFS_IOC_UNRESVSP64: |
440 | case XFS_IOC_FSGEOMETRY_V1: | 651 | case XFS_IOC_FSGEOMETRY_V1: |
441 | break; | 652 | case XFS_IOC_FSGROWFSDATA: |
653 | case XFS_IOC_FSGROWFSRT: | ||
654 | return xfs_file_ioctl(filp, cmd, p); | ||
655 | #else | ||
656 | case XFS_IOC_ALLOCSP_32: | ||
657 | case XFS_IOC_FREESP_32: | ||
658 | case XFS_IOC_ALLOCSP64_32: | ||
659 | case XFS_IOC_FREESP64_32: | ||
660 | case XFS_IOC_RESVSP_32: | ||
661 | case XFS_IOC_UNRESVSP_32: | ||
662 | case XFS_IOC_RESVSP64_32: | ||
663 | case XFS_IOC_UNRESVSP64_32: { | ||
664 | struct xfs_flock64 bf; | ||
442 | 665 | ||
443 | /* xfs_bstat_t still has wrong u32 vs u64 alignment */ | 666 | if (xfs_compat_flock64_copyin(&bf, arg)) |
444 | case XFS_IOC_SWAPEXT: | 667 | return -XFS_ERROR(EFAULT); |
445 | break; | 668 | cmd = _NATIVE_IOC(cmd, struct xfs_flock64); |
669 | return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf); | ||
670 | } | ||
671 | case XFS_IOC_FSGEOMETRY_V1_32: | ||
672 | return xfs_compat_ioc_fsgeometry_v1(mp, arg); | ||
673 | case XFS_IOC_FSGROWFSDATA_32: { | ||
674 | struct xfs_growfs_data in; | ||
675 | |||
676 | if (xfs_compat_growfs_data_copyin(&in, arg)) | ||
677 | return -XFS_ERROR(EFAULT); | ||
678 | error = xfs_growfs_data(mp, &in); | ||
679 | return -error; | ||
680 | } | ||
681 | case XFS_IOC_FSGROWFSRT_32: { | ||
682 | struct xfs_growfs_rt in; | ||
446 | 683 | ||
684 | if (xfs_compat_growfs_rt_copyin(&in, arg)) | ||
685 | return -XFS_ERROR(EFAULT); | ||
686 | error = xfs_growfs_rt(mp, &in); | ||
687 | return -error; | ||
688 | } | ||
447 | #endif | 689 | #endif |
690 | /* long changes size, but xfs only copiese out 32 bits */ | ||
691 | case XFS_IOC_GETXFLAGS_32: | ||
692 | case XFS_IOC_SETXFLAGS_32: | ||
693 | case XFS_IOC_GETVERSION_32: | ||
694 | cmd = _NATIVE_IOC(cmd, long); | ||
695 | return xfs_file_ioctl(filp, cmd, p); | ||
696 | case XFS_IOC_SWAPEXT: { | ||
697 | struct xfs_swapext sxp; | ||
698 | struct compat_xfs_swapext __user *sxu = arg; | ||
699 | |||
700 | /* Bulk copy in up to the sx_stat field, then copy bstat */ | ||
701 | if (copy_from_user(&sxp, sxu, | ||
702 | offsetof(struct xfs_swapext, sx_stat)) || | ||
703 | xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat)) | ||
704 | return -XFS_ERROR(EFAULT); | ||
705 | error = xfs_swapext(&sxp); | ||
706 | return -error; | ||
707 | } | ||
448 | case XFS_IOC_FSBULKSTAT_32: | 708 | case XFS_IOC_FSBULKSTAT_32: |
449 | case XFS_IOC_FSBULKSTAT_SINGLE_32: | 709 | case XFS_IOC_FSBULKSTAT_SINGLE_32: |
450 | case XFS_IOC_FSINUMBERS_32: | 710 | case XFS_IOC_FSINUMBERS_32: |
451 | cmd = _NATIVE_IOC(cmd, struct xfs_fsop_bulkreq); | 711 | return xfs_compat_ioc_bulkstat(mp, cmd, arg); |
452 | return xfs_ioc_bulkstat_compat(XFS_I(inode)->i_mount, | ||
453 | cmd, (void __user*)arg); | ||
454 | case XFS_IOC_FD_TO_HANDLE_32: | 712 | case XFS_IOC_FD_TO_HANDLE_32: |
455 | case XFS_IOC_PATH_TO_HANDLE_32: | 713 | case XFS_IOC_PATH_TO_HANDLE_32: |
456 | case XFS_IOC_PATH_TO_FSHANDLE_32: | 714 | case XFS_IOC_PATH_TO_FSHANDLE_32: { |
457 | case XFS_IOC_OPEN_BY_HANDLE_32: | 715 | struct xfs_fsop_handlereq hreq; |
458 | case XFS_IOC_READLINK_BY_HANDLE_32: | 716 | |
459 | arg = xfs_ioctl32_fshandle(arg); | 717 | if (xfs_compat_handlereq_copyin(&hreq, arg)) |
718 | return -XFS_ERROR(EFAULT); | ||
460 | cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq); | 719 | cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq); |
461 | break; | 720 | return xfs_find_handle(cmd, &hreq); |
462 | default: | ||
463 | return -ENOIOCTLCMD; | ||
464 | } | 721 | } |
722 | case XFS_IOC_OPEN_BY_HANDLE_32: { | ||
723 | struct xfs_fsop_handlereq hreq; | ||
465 | 724 | ||
466 | error = xfs_ioctl(XFS_I(inode), file, mode, cmd, (void __user *)arg); | 725 | if (xfs_compat_handlereq_copyin(&hreq, arg)) |
467 | xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED); | 726 | return -XFS_ERROR(EFAULT); |
468 | 727 | return xfs_open_by_handle(mp, &hreq, filp, inode); | |
469 | return error; | 728 | } |
470 | } | 729 | case XFS_IOC_READLINK_BY_HANDLE_32: { |
471 | 730 | struct xfs_fsop_handlereq hreq; | |
472 | long | ||
473 | xfs_file_compat_ioctl( | ||
474 | struct file *file, | ||
475 | unsigned cmd, | ||
476 | unsigned long arg) | ||
477 | { | ||
478 | return xfs_compat_ioctl(0, file, cmd, arg); | ||
479 | } | ||
480 | 731 | ||
481 | long | 732 | if (xfs_compat_handlereq_copyin(&hreq, arg)) |
482 | xfs_file_compat_invis_ioctl( | 733 | return -XFS_ERROR(EFAULT); |
483 | struct file *file, | 734 | return xfs_readlink_by_handle(mp, &hreq, inode); |
484 | unsigned cmd, | 735 | } |
485 | unsigned long arg) | 736 | case XFS_IOC_ATTRLIST_BY_HANDLE_32: |
486 | { | 737 | return xfs_compat_attrlist_by_handle(mp, arg, inode); |
487 | return xfs_compat_ioctl(IO_INVIS, file, cmd, arg); | 738 | case XFS_IOC_ATTRMULTI_BY_HANDLE_32: |
739 | return xfs_compat_attrmulti_by_handle(mp, arg, inode); | ||
740 | case XFS_IOC_FSSETDM_BY_HANDLE_32: | ||
741 | return xfs_compat_fssetdm_by_handle(mp, arg, inode); | ||
742 | default: | ||
743 | return -XFS_ERROR(ENOIOCTLCMD); | ||
744 | } | ||
488 | } | 745 | } |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h index 02de6e62ee37..1024c4f8ba0d 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.h +++ b/fs/xfs/linux-2.6/xfs_ioctl32.h | |||
@@ -18,7 +18,217 @@ | |||
18 | #ifndef __XFS_IOCTL32_H__ | 18 | #ifndef __XFS_IOCTL32_H__ |
19 | #define __XFS_IOCTL32_H__ | 19 | #define __XFS_IOCTL32_H__ |
20 | 20 | ||
21 | extern long xfs_file_compat_ioctl(struct file *, unsigned, unsigned long); | 21 | #include <linux/compat.h> |
22 | extern long xfs_file_compat_invis_ioctl(struct file *, unsigned, unsigned long); | 22 | |
23 | /* | ||
24 | * on 32-bit arches, ioctl argument structures may have different sizes | ||
25 | * and/or alignment. We define compat structures which match the | ||
26 | * 32-bit sizes/alignments here, and their associated ioctl numbers. | ||
27 | * | ||
28 | * xfs_ioctl32.c contains routines to copy these structures in and out. | ||
29 | */ | ||
30 | |||
31 | /* stock kernel-level ioctls we support */ | ||
32 | #define XFS_IOC_GETXFLAGS_32 FS_IOC32_GETFLAGS | ||
33 | #define XFS_IOC_SETXFLAGS_32 FS_IOC32_SETFLAGS | ||
34 | #define XFS_IOC_GETVERSION_32 FS_IOC32_GETVERSION | ||
35 | |||
36 | /* | ||
37 | * On intel, even if sizes match, alignment and/or padding may differ. | ||
38 | */ | ||
39 | #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) | ||
40 | #define BROKEN_X86_ALIGNMENT | ||
41 | #define __compat_packed __attribute__((packed)) | ||
42 | #else | ||
43 | #define __compat_packed | ||
44 | #endif | ||
45 | |||
46 | typedef struct compat_xfs_bstime { | ||
47 | compat_time_t tv_sec; /* seconds */ | ||
48 | __s32 tv_nsec; /* and nanoseconds */ | ||
49 | } compat_xfs_bstime_t; | ||
50 | |||
51 | typedef struct compat_xfs_bstat { | ||
52 | __u64 bs_ino; /* inode number */ | ||
53 | __u16 bs_mode; /* type and mode */ | ||
54 | __u16 bs_nlink; /* number of links */ | ||
55 | __u32 bs_uid; /* user id */ | ||
56 | __u32 bs_gid; /* group id */ | ||
57 | __u32 bs_rdev; /* device value */ | ||
58 | __s32 bs_blksize; /* block size */ | ||
59 | __s64 bs_size; /* file size */ | ||
60 | compat_xfs_bstime_t bs_atime; /* access time */ | ||
61 | compat_xfs_bstime_t bs_mtime; /* modify time */ | ||
62 | compat_xfs_bstime_t bs_ctime; /* inode change time */ | ||
63 | int64_t bs_blocks; /* number of blocks */ | ||
64 | __u32 bs_xflags; /* extended flags */ | ||
65 | __s32 bs_extsize; /* extent size */ | ||
66 | __s32 bs_extents; /* number of extents */ | ||
67 | __u32 bs_gen; /* generation count */ | ||
68 | __u16 bs_projid; /* project id */ | ||
69 | unsigned char bs_pad[14]; /* pad space, unused */ | ||
70 | __u32 bs_dmevmask; /* DMIG event mask */ | ||
71 | __u16 bs_dmstate; /* DMIG state info */ | ||
72 | __u16 bs_aextents; /* attribute number of extents */ | ||
73 | } __compat_packed compat_xfs_bstat_t; | ||
74 | |||
75 | typedef struct compat_xfs_fsop_bulkreq { | ||
76 | compat_uptr_t lastip; /* last inode # pointer */ | ||
77 | __s32 icount; /* count of entries in buffer */ | ||
78 | compat_uptr_t ubuffer; /* user buffer for inode desc. */ | ||
79 | compat_uptr_t ocount; /* output count pointer */ | ||
80 | } compat_xfs_fsop_bulkreq_t; | ||
81 | |||
82 | #define XFS_IOC_FSBULKSTAT_32 \ | ||
83 | _IOWR('X', 101, struct compat_xfs_fsop_bulkreq) | ||
84 | #define XFS_IOC_FSBULKSTAT_SINGLE_32 \ | ||
85 | _IOWR('X', 102, struct compat_xfs_fsop_bulkreq) | ||
86 | #define XFS_IOC_FSINUMBERS_32 \ | ||
87 | _IOWR('X', 103, struct compat_xfs_fsop_bulkreq) | ||
88 | |||
89 | typedef struct compat_xfs_fsop_handlereq { | ||
90 | __u32 fd; /* fd for FD_TO_HANDLE */ | ||
91 | compat_uptr_t path; /* user pathname */ | ||
92 | __u32 oflags; /* open flags */ | ||
93 | compat_uptr_t ihandle; /* user supplied handle */ | ||
94 | __u32 ihandlen; /* user supplied length */ | ||
95 | compat_uptr_t ohandle; /* user buffer for handle */ | ||
96 | compat_uptr_t ohandlen; /* user buffer length */ | ||
97 | } compat_xfs_fsop_handlereq_t; | ||
98 | |||
99 | #define XFS_IOC_PATH_TO_FSHANDLE_32 \ | ||
100 | _IOWR('X', 104, struct compat_xfs_fsop_handlereq) | ||
101 | #define XFS_IOC_PATH_TO_HANDLE_32 \ | ||
102 | _IOWR('X', 105, struct compat_xfs_fsop_handlereq) | ||
103 | #define XFS_IOC_FD_TO_HANDLE_32 \ | ||
104 | _IOWR('X', 106, struct compat_xfs_fsop_handlereq) | ||
105 | #define XFS_IOC_OPEN_BY_HANDLE_32 \ | ||
106 | _IOWR('X', 107, struct compat_xfs_fsop_handlereq) | ||
107 | #define XFS_IOC_READLINK_BY_HANDLE_32 \ | ||
108 | _IOWR('X', 108, struct compat_xfs_fsop_handlereq) | ||
109 | |||
110 | /* The bstat field in the swapext struct needs translation */ | ||
111 | typedef struct compat_xfs_swapext { | ||
112 | __int64_t sx_version; /* version */ | ||
113 | __int64_t sx_fdtarget; /* fd of target file */ | ||
114 | __int64_t sx_fdtmp; /* fd of tmp file */ | ||
115 | xfs_off_t sx_offset; /* offset into file */ | ||
116 | xfs_off_t sx_length; /* leng from offset */ | ||
117 | char sx_pad[16]; /* pad space, unused */ | ||
118 | compat_xfs_bstat_t sx_stat; /* stat of target b4 copy */ | ||
119 | } __compat_packed compat_xfs_swapext_t; | ||
120 | |||
121 | #define XFS_IOC_SWAPEXT_32 _IOWR('X', 109, struct compat_xfs_swapext) | ||
122 | |||
123 | typedef struct compat_xfs_fsop_attrlist_handlereq { | ||
124 | struct compat_xfs_fsop_handlereq hreq; /* handle interface structure */ | ||
125 | struct xfs_attrlist_cursor pos; /* opaque cookie, list offset */ | ||
126 | __u32 flags; /* which namespace to use */ | ||
127 | __u32 buflen; /* length of buffer supplied */ | ||
128 | compat_uptr_t buffer; /* returned names */ | ||
129 | } __compat_packed compat_xfs_fsop_attrlist_handlereq_t; | ||
130 | |||
131 | /* Note: actually this is read/write */ | ||
132 | #define XFS_IOC_ATTRLIST_BY_HANDLE_32 \ | ||
133 | _IOW('X', 122, struct compat_xfs_fsop_attrlist_handlereq) | ||
134 | |||
135 | /* am_opcodes defined in xfs_fs.h */ | ||
136 | typedef struct compat_xfs_attr_multiop { | ||
137 | __u32 am_opcode; | ||
138 | __s32 am_error; | ||
139 | compat_uptr_t am_attrname; | ||
140 | compat_uptr_t am_attrvalue; | ||
141 | __u32 am_length; | ||
142 | __u32 am_flags; | ||
143 | } compat_xfs_attr_multiop_t; | ||
144 | |||
145 | typedef struct compat_xfs_fsop_attrmulti_handlereq { | ||
146 | struct compat_xfs_fsop_handlereq hreq; /* handle interface structure */ | ||
147 | __u32 opcount;/* count of following multiop */ | ||
148 | /* ptr to compat_xfs_attr_multiop */ | ||
149 | compat_uptr_t ops; /* attr_multi data */ | ||
150 | } compat_xfs_fsop_attrmulti_handlereq_t; | ||
151 | |||
152 | #define XFS_IOC_ATTRMULTI_BY_HANDLE_32 \ | ||
153 | _IOW('X', 123, struct compat_xfs_fsop_attrmulti_handlereq) | ||
154 | |||
155 | typedef struct compat_xfs_fsop_setdm_handlereq { | ||
156 | struct compat_xfs_fsop_handlereq hreq; /* handle information */ | ||
157 | /* ptr to struct fsdmidata */ | ||
158 | compat_uptr_t data; /* DMAPI data */ | ||
159 | } compat_xfs_fsop_setdm_handlereq_t; | ||
160 | |||
161 | #define XFS_IOC_FSSETDM_BY_HANDLE_32 \ | ||
162 | _IOW('X', 121, struct compat_xfs_fsop_setdm_handlereq) | ||
163 | |||
164 | #ifdef BROKEN_X86_ALIGNMENT | ||
165 | /* on ia32 l_start is on a 32-bit boundary */ | ||
166 | typedef struct compat_xfs_flock64 { | ||
167 | __s16 l_type; | ||
168 | __s16 l_whence; | ||
169 | __s64 l_start __attribute__((packed)); | ||
170 | /* len == 0 means until end of file */ | ||
171 | __s64 l_len __attribute__((packed)); | ||
172 | __s32 l_sysid; | ||
173 | __u32 l_pid; | ||
174 | __s32 l_pad[4]; /* reserve area */ | ||
175 | } compat_xfs_flock64_t; | ||
176 | |||
177 | #define XFS_IOC_ALLOCSP_32 _IOW('X', 10, struct compat_xfs_flock64) | ||
178 | #define XFS_IOC_FREESP_32 _IOW('X', 11, struct compat_xfs_flock64) | ||
179 | #define XFS_IOC_ALLOCSP64_32 _IOW('X', 36, struct compat_xfs_flock64) | ||
180 | #define XFS_IOC_FREESP64_32 _IOW('X', 37, struct compat_xfs_flock64) | ||
181 | #define XFS_IOC_RESVSP_32 _IOW('X', 40, struct compat_xfs_flock64) | ||
182 | #define XFS_IOC_UNRESVSP_32 _IOW('X', 41, struct compat_xfs_flock64) | ||
183 | #define XFS_IOC_RESVSP64_32 _IOW('X', 42, struct compat_xfs_flock64) | ||
184 | #define XFS_IOC_UNRESVSP64_32 _IOW('X', 43, struct compat_xfs_flock64) | ||
185 | |||
186 | typedef struct compat_xfs_fsop_geom_v1 { | ||
187 | __u32 blocksize; /* filesystem (data) block size */ | ||
188 | __u32 rtextsize; /* realtime extent size */ | ||
189 | __u32 agblocks; /* fsblocks in an AG */ | ||
190 | __u32 agcount; /* number of allocation groups */ | ||
191 | __u32 logblocks; /* fsblocks in the log */ | ||
192 | __u32 sectsize; /* (data) sector size, bytes */ | ||
193 | __u32 inodesize; /* inode size in bytes */ | ||
194 | __u32 imaxpct; /* max allowed inode space(%) */ | ||
195 | __u64 datablocks; /* fsblocks in data subvolume */ | ||
196 | __u64 rtblocks; /* fsblocks in realtime subvol */ | ||
197 | __u64 rtextents; /* rt extents in realtime subvol*/ | ||
198 | __u64 logstart; /* starting fsblock of the log */ | ||
199 | unsigned char uuid[16]; /* unique id of the filesystem */ | ||
200 | __u32 sunit; /* stripe unit, fsblocks */ | ||
201 | __u32 swidth; /* stripe width, fsblocks */ | ||
202 | __s32 version; /* structure version */ | ||
203 | __u32 flags; /* superblock version flags */ | ||
204 | __u32 logsectsize; /* log sector size, bytes */ | ||
205 | __u32 rtsectsize; /* realtime sector size, bytes */ | ||
206 | __u32 dirblocksize; /* directory block size, bytes */ | ||
207 | } __attribute__((packed)) compat_xfs_fsop_geom_v1_t; | ||
208 | |||
209 | #define XFS_IOC_FSGEOMETRY_V1_32 \ | ||
210 | _IOR('X', 100, struct compat_xfs_fsop_geom_v1) | ||
211 | |||
212 | typedef struct compat_xfs_inogrp { | ||
213 | __u64 xi_startino; /* starting inode number */ | ||
214 | __s32 xi_alloccount; /* # bits set in allocmask */ | ||
215 | __u64 xi_allocmask; /* mask of allocated inodes */ | ||
216 | } __attribute__((packed)) compat_xfs_inogrp_t; | ||
217 | |||
218 | /* These growfs input structures have padding on the end, so must translate */ | ||
219 | typedef struct compat_xfs_growfs_data { | ||
220 | __u64 newblocks; /* new data subvol size, fsblocks */ | ||
221 | __u32 imaxpct; /* new inode space percentage limit */ | ||
222 | } __attribute__((packed)) compat_xfs_growfs_data_t; | ||
223 | |||
224 | typedef struct compat_xfs_growfs_rt { | ||
225 | __u64 newblocks; /* new realtime size, fsblocks */ | ||
226 | __u32 extsize; /* new realtime extent size, fsblocks */ | ||
227 | } __attribute__((packed)) compat_xfs_growfs_rt_t; | ||
228 | |||
229 | #define XFS_IOC_FSGROWFSDATA_32 _IOW('X', 110, struct compat_xfs_growfs_data) | ||
230 | #define XFS_IOC_FSGROWFSRT_32 _IOW('X', 112, struct compat_xfs_growfs_rt) | ||
231 | |||
232 | #endif /* BROKEN_X86_ALIGNMENT */ | ||
23 | 233 | ||
24 | #endif /* __XFS_IOCTL32_H__ */ | 234 | #endif /* __XFS_IOCTL32_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 095d271f3434..7aa53fefc67f 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/namei.h> | 53 | #include <linux/namei.h> |
54 | #include <linux/security.h> | 54 | #include <linux/security.h> |
55 | #include <linux/falloc.h> | 55 | #include <linux/falloc.h> |
56 | #include <linux/fiemap.h> | ||
56 | 57 | ||
57 | /* | 58 | /* |
58 | * Bring the atime in the XFS inode uptodate. | 59 | * Bring the atime in the XFS inode uptodate. |
@@ -64,14 +65,14 @@ xfs_synchronize_atime( | |||
64 | { | 65 | { |
65 | struct inode *inode = VFS_I(ip); | 66 | struct inode *inode = VFS_I(ip); |
66 | 67 | ||
67 | if (inode) { | 68 | if (!(inode->i_state & I_CLEAR)) { |
68 | ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; | 69 | ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; |
69 | ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; | 70 | ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; |
70 | } | 71 | } |
71 | } | 72 | } |
72 | 73 | ||
73 | /* | 74 | /* |
74 | * If the linux inode exists, mark it dirty. | 75 | * If the linux inode is valid, mark it dirty. |
75 | * Used when commiting a dirty inode into a transaction so that | 76 | * Used when commiting a dirty inode into a transaction so that |
76 | * the inode will get written back by the linux code | 77 | * the inode will get written back by the linux code |
77 | */ | 78 | */ |
@@ -81,7 +82,7 @@ xfs_mark_inode_dirty_sync( | |||
81 | { | 82 | { |
82 | struct inode *inode = VFS_I(ip); | 83 | struct inode *inode = VFS_I(ip); |
83 | 84 | ||
84 | if (inode) | 85 | if (!(inode->i_state & (I_WILL_FREE|I_FREEING|I_CLEAR))) |
85 | mark_inode_dirty_sync(inode); | 86 | mark_inode_dirty_sync(inode); |
86 | } | 87 | } |
87 | 88 | ||
@@ -128,7 +129,7 @@ xfs_ichgtime( | |||
128 | if (sync_it) { | 129 | if (sync_it) { |
129 | SYNCHRONIZE(); | 130 | SYNCHRONIZE(); |
130 | ip->i_update_core = 1; | 131 | ip->i_update_core = 1; |
131 | mark_inode_dirty_sync(inode); | 132 | xfs_mark_inode_dirty_sync(ip); |
132 | } | 133 | } |
133 | } | 134 | } |
134 | 135 | ||
@@ -158,8 +159,6 @@ xfs_init_security( | |||
158 | } | 159 | } |
159 | 160 | ||
160 | error = xfs_attr_set(ip, name, value, length, ATTR_SECURE); | 161 | error = xfs_attr_set(ip, name, value, length, ATTR_SECURE); |
161 | if (!error) | ||
162 | xfs_iflags_set(ip, XFS_IMODIFIED); | ||
163 | 162 | ||
164 | kfree(name); | 163 | kfree(name); |
165 | kfree(value); | 164 | kfree(value); |
@@ -260,7 +259,6 @@ xfs_vn_mknod( | |||
260 | error = _ACL_INHERIT(inode, mode, default_acl); | 259 | error = _ACL_INHERIT(inode, mode, default_acl); |
261 | if (unlikely(error)) | 260 | if (unlikely(error)) |
262 | goto out_cleanup_inode; | 261 | goto out_cleanup_inode; |
263 | xfs_iflags_set(ip, XFS_IMODIFIED); | ||
264 | _ACL_FREE(default_acl); | 262 | _ACL_FREE(default_acl); |
265 | } | 263 | } |
266 | 264 | ||
@@ -366,21 +364,17 @@ xfs_vn_link( | |||
366 | struct inode *dir, | 364 | struct inode *dir, |
367 | struct dentry *dentry) | 365 | struct dentry *dentry) |
368 | { | 366 | { |
369 | struct inode *inode; /* inode of guy being linked to */ | 367 | struct inode *inode = old_dentry->d_inode; |
370 | struct xfs_name name; | 368 | struct xfs_name name; |
371 | int error; | 369 | int error; |
372 | 370 | ||
373 | inode = old_dentry->d_inode; | ||
374 | xfs_dentry_to_name(&name, dentry); | 371 | xfs_dentry_to_name(&name, dentry); |
375 | 372 | ||
376 | igrab(inode); | ||
377 | error = xfs_link(XFS_I(dir), XFS_I(inode), &name); | 373 | error = xfs_link(XFS_I(dir), XFS_I(inode), &name); |
378 | if (unlikely(error)) { | 374 | if (unlikely(error)) |
379 | iput(inode); | ||
380 | return -error; | 375 | return -error; |
381 | } | ||
382 | 376 | ||
383 | xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED); | 377 | atomic_inc(&inode->i_count); |
384 | d_instantiate(dentry, inode); | 378 | d_instantiate(dentry, inode); |
385 | return 0; | 379 | return 0; |
386 | } | 380 | } |
@@ -601,7 +595,7 @@ xfs_vn_setattr( | |||
601 | struct dentry *dentry, | 595 | struct dentry *dentry, |
602 | struct iattr *iattr) | 596 | struct iattr *iattr) |
603 | { | 597 | { |
604 | return -xfs_setattr(XFS_I(dentry->d_inode), iattr, 0, NULL); | 598 | return -xfs_setattr(XFS_I(dentry->d_inode), iattr, 0); |
605 | } | 599 | } |
606 | 600 | ||
607 | /* | 601 | /* |
@@ -642,7 +636,7 @@ xfs_vn_fallocate( | |||
642 | 636 | ||
643 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 637 | xfs_ilock(ip, XFS_IOLOCK_EXCL); |
644 | error = xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf, | 638 | error = xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf, |
645 | 0, NULL, XFS_ATTR_NOLOCK); | 639 | 0, XFS_ATTR_NOLOCK); |
646 | if (!error && !(mode & FALLOC_FL_KEEP_SIZE) && | 640 | if (!error && !(mode & FALLOC_FL_KEEP_SIZE) && |
647 | offset + len > i_size_read(inode)) | 641 | offset + len > i_size_read(inode)) |
648 | new_size = offset + len; | 642 | new_size = offset + len; |
@@ -653,7 +647,7 @@ xfs_vn_fallocate( | |||
653 | 647 | ||
654 | iattr.ia_valid = ATTR_SIZE; | 648 | iattr.ia_valid = ATTR_SIZE; |
655 | iattr.ia_size = new_size; | 649 | iattr.ia_size = new_size; |
656 | error = xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK, NULL); | 650 | error = xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK); |
657 | } | 651 | } |
658 | 652 | ||
659 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 653 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); |
@@ -661,6 +655,88 @@ out_error: | |||
661 | return error; | 655 | return error; |
662 | } | 656 | } |
663 | 657 | ||
658 | #define XFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR) | ||
659 | |||
660 | /* | ||
661 | * Call fiemap helper to fill in user data. | ||
662 | * Returns positive errors to xfs_getbmap. | ||
663 | */ | ||
664 | STATIC int | ||
665 | xfs_fiemap_format( | ||
666 | void **arg, | ||
667 | struct getbmapx *bmv, | ||
668 | int *full) | ||
669 | { | ||
670 | int error; | ||
671 | struct fiemap_extent_info *fieinfo = *arg; | ||
672 | u32 fiemap_flags = 0; | ||
673 | u64 logical, physical, length; | ||
674 | |||
675 | /* Do nothing for a hole */ | ||
676 | if (bmv->bmv_block == -1LL) | ||
677 | return 0; | ||
678 | |||
679 | logical = BBTOB(bmv->bmv_offset); | ||
680 | physical = BBTOB(bmv->bmv_block); | ||
681 | length = BBTOB(bmv->bmv_length); | ||
682 | |||
683 | if (bmv->bmv_oflags & BMV_OF_PREALLOC) | ||
684 | fiemap_flags |= FIEMAP_EXTENT_UNWRITTEN; | ||
685 | else if (bmv->bmv_oflags & BMV_OF_DELALLOC) { | ||
686 | fiemap_flags |= FIEMAP_EXTENT_DELALLOC; | ||
687 | physical = 0; /* no block yet */ | ||
688 | } | ||
689 | if (bmv->bmv_oflags & BMV_OF_LAST) | ||
690 | fiemap_flags |= FIEMAP_EXTENT_LAST; | ||
691 | |||
692 | error = fiemap_fill_next_extent(fieinfo, logical, physical, | ||
693 | length, fiemap_flags); | ||
694 | if (error > 0) { | ||
695 | error = 0; | ||
696 | *full = 1; /* user array now full */ | ||
697 | } | ||
698 | |||
699 | return -error; | ||
700 | } | ||
701 | |||
702 | STATIC int | ||
703 | xfs_vn_fiemap( | ||
704 | struct inode *inode, | ||
705 | struct fiemap_extent_info *fieinfo, | ||
706 | u64 start, | ||
707 | u64 length) | ||
708 | { | ||
709 | xfs_inode_t *ip = XFS_I(inode); | ||
710 | struct getbmapx bm; | ||
711 | int error; | ||
712 | |||
713 | error = fiemap_check_flags(fieinfo, XFS_FIEMAP_FLAGS); | ||
714 | if (error) | ||
715 | return error; | ||
716 | |||
717 | /* Set up bmap header for xfs internal routine */ | ||
718 | bm.bmv_offset = BTOBB(start); | ||
719 | /* Special case for whole file */ | ||
720 | if (length == FIEMAP_MAX_OFFSET) | ||
721 | bm.bmv_length = -1LL; | ||
722 | else | ||
723 | bm.bmv_length = BTOBB(length); | ||
724 | |||
725 | /* our formatter will tell xfs_getbmap when to stop. */ | ||
726 | bm.bmv_count = MAXEXTNUM; | ||
727 | bm.bmv_iflags = BMV_IF_PREALLOC; | ||
728 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) | ||
729 | bm.bmv_iflags |= BMV_IF_ATTRFORK; | ||
730 | if (!(fieinfo->fi_flags & FIEMAP_FLAG_SYNC)) | ||
731 | bm.bmv_iflags |= BMV_IF_DELALLOC; | ||
732 | |||
733 | error = xfs_getbmap(ip, &bm, xfs_fiemap_format, fieinfo); | ||
734 | if (error) | ||
735 | return -error; | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
664 | static const struct inode_operations xfs_inode_operations = { | 740 | static const struct inode_operations xfs_inode_operations = { |
665 | .permission = xfs_vn_permission, | 741 | .permission = xfs_vn_permission, |
666 | .truncate = xfs_vn_truncate, | 742 | .truncate = xfs_vn_truncate, |
@@ -671,6 +747,7 @@ static const struct inode_operations xfs_inode_operations = { | |||
671 | .removexattr = generic_removexattr, | 747 | .removexattr = generic_removexattr, |
672 | .listxattr = xfs_vn_listxattr, | 748 | .listxattr = xfs_vn_listxattr, |
673 | .fallocate = xfs_vn_fallocate, | 749 | .fallocate = xfs_vn_fallocate, |
750 | .fiemap = xfs_vn_fiemap, | ||
674 | }; | 751 | }; |
675 | 752 | ||
676 | static const struct inode_operations xfs_dir_inode_operations = { | 753 | static const struct inode_operations xfs_dir_inode_operations = { |
@@ -766,12 +843,20 @@ xfs_diflags_to_iflags( | |||
766 | * When reading existing inodes from disk this is called directly | 843 | * When reading existing inodes from disk this is called directly |
767 | * from xfs_iget, when creating a new inode it is called from | 844 | * from xfs_iget, when creating a new inode it is called from |
768 | * xfs_ialloc after setting up the inode. | 845 | * xfs_ialloc after setting up the inode. |
846 | * | ||
847 | * We are always called with an uninitialised linux inode here. | ||
848 | * We need to initialise the necessary fields and take a reference | ||
849 | * on it. | ||
769 | */ | 850 | */ |
770 | void | 851 | void |
771 | xfs_setup_inode( | 852 | xfs_setup_inode( |
772 | struct xfs_inode *ip) | 853 | struct xfs_inode *ip) |
773 | { | 854 | { |
774 | struct inode *inode = ip->i_vnode; | 855 | struct inode *inode = &ip->i_vnode; |
856 | |||
857 | inode->i_ino = ip->i_ino; | ||
858 | inode->i_state = I_NEW|I_LOCK; | ||
859 | inode_add_to_lists(ip->i_mount->m_super, inode); | ||
775 | 860 | ||
776 | inode->i_mode = ip->i_d.di_mode; | 861 | inode->i_mode = ip->i_d.di_mode; |
777 | inode->i_nlink = ip->i_d.di_nlink; | 862 | inode->i_nlink = ip->i_d.di_nlink; |
@@ -799,7 +884,6 @@ xfs_setup_inode( | |||
799 | inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec; | 884 | inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec; |
800 | inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec; | 885 | inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec; |
801 | xfs_diflags_to_iflags(inode, ip); | 886 | xfs_diflags_to_iflags(inode, ip); |
802 | xfs_iflags_clear(ip, XFS_IMODIFIED); | ||
803 | 887 | ||
804 | switch (inode->i_mode & S_IFMT) { | 888 | switch (inode->i_mode & S_IFMT) { |
805 | case S_IFREG: | 889 | case S_IFREG: |
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index 8b1a1e31dc21..ef41c92ce66e 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h | |||
@@ -22,7 +22,6 @@ struct xfs_inode; | |||
22 | 22 | ||
23 | extern const struct file_operations xfs_file_operations; | 23 | extern const struct file_operations xfs_file_operations; |
24 | extern const struct file_operations xfs_dir_file_operations; | 24 | extern const struct file_operations xfs_dir_file_operations; |
25 | extern const struct file_operations xfs_invis_file_operations; | ||
26 | 25 | ||
27 | extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size); | 26 | extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size); |
28 | 27 | ||
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index cc0f7b3a9795..507492d6dccd 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
@@ -21,18 +21,12 @@ | |||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * Some types are conditional depending on the target system. | ||
25 | * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits. | 24 | * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits. |
26 | * XFS_BIG_INUMS needs the VFS inode number to be 64 bits, as well | 25 | * XFS_BIG_INUMS requires XFS_BIG_BLKNOS to be set. |
27 | * as requiring XFS_BIG_BLKNOS to be set. | ||
28 | */ | 26 | */ |
29 | #if defined(CONFIG_LBD) || (BITS_PER_LONG == 64) | 27 | #if defined(CONFIG_LBD) || (BITS_PER_LONG == 64) |
30 | # define XFS_BIG_BLKNOS 1 | 28 | # define XFS_BIG_BLKNOS 1 |
31 | # if BITS_PER_LONG == 64 | 29 | # define XFS_BIG_INUMS 1 |
32 | # define XFS_BIG_INUMS 1 | ||
33 | # else | ||
34 | # define XFS_BIG_INUMS 0 | ||
35 | # endif | ||
36 | #else | 30 | #else |
37 | # define XFS_BIG_BLKNOS 0 | 31 | # define XFS_BIG_BLKNOS 0 |
38 | # define XFS_BIG_INUMS 0 | 32 | # define XFS_BIG_INUMS 0 |
@@ -77,6 +71,7 @@ | |||
77 | #include <linux/spinlock.h> | 71 | #include <linux/spinlock.h> |
78 | #include <linux/random.h> | 72 | #include <linux/random.h> |
79 | #include <linux/ctype.h> | 73 | #include <linux/ctype.h> |
74 | #include <linux/writeback.h> | ||
80 | 75 | ||
81 | #include <asm/page.h> | 76 | #include <asm/page.h> |
82 | #include <asm/div64.h> | 77 | #include <asm/div64.h> |
@@ -85,7 +80,6 @@ | |||
85 | #include <asm/byteorder.h> | 80 | #include <asm/byteorder.h> |
86 | #include <asm/unaligned.h> | 81 | #include <asm/unaligned.h> |
87 | 82 | ||
88 | #include <xfs_vfs.h> | ||
89 | #include <xfs_cred.h> | 83 | #include <xfs_cred.h> |
90 | #include <xfs_vnode.h> | 84 | #include <xfs_vnode.h> |
91 | #include <xfs_stats.h> | 85 | #include <xfs_stats.h> |
@@ -107,7 +101,6 @@ | |||
107 | #undef HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ | 101 | #undef HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ |
108 | #endif | 102 | #endif |
109 | 103 | ||
110 | #define restricted_chown xfs_params.restrict_chown.val | ||
111 | #define irix_sgid_inherit xfs_params.sgid_inherit.val | 104 | #define irix_sgid_inherit xfs_params.sgid_inherit.val |
112 | #define irix_symlink_mode xfs_params.symlink_mode.val | 105 | #define irix_symlink_mode xfs_params.symlink_mode.val |
113 | #define xfs_panic_mask xfs_params.panic_mask.val | 106 | #define xfs_panic_mask xfs_params.panic_mask.val |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 1957e5357d04..7e90daa0d1d1 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #include "xfs_vnodeops.h" | 51 | #include "xfs_vnodeops.h" |
52 | 52 | ||
53 | #include <linux/capability.h> | 53 | #include <linux/capability.h> |
54 | #include <linux/mount.h> | ||
55 | #include <linux/writeback.h> | 54 | #include <linux/writeback.h> |
56 | 55 | ||
57 | 56 | ||
@@ -243,7 +242,7 @@ xfs_read( | |||
243 | 242 | ||
244 | if (unlikely(ioflags & IO_ISDIRECT)) { | 243 | if (unlikely(ioflags & IO_ISDIRECT)) { |
245 | if (inode->i_mapping->nrpages) | 244 | if (inode->i_mapping->nrpages) |
246 | ret = xfs_flushinval_pages(ip, (*offset & PAGE_CACHE_MASK), | 245 | ret = -xfs_flushinval_pages(ip, (*offset & PAGE_CACHE_MASK), |
247 | -1, FI_REMAPF_LOCKED); | 246 | -1, FI_REMAPF_LOCKED); |
248 | mutex_unlock(&inode->i_mutex); | 247 | mutex_unlock(&inode->i_mutex); |
249 | if (ret) { | 248 | if (ret) { |
@@ -668,15 +667,8 @@ start: | |||
668 | if (new_size > xip->i_size) | 667 | if (new_size > xip->i_size) |
669 | xip->i_new_size = new_size; | 668 | xip->i_new_size = new_size; |
670 | 669 | ||
671 | /* | 670 | if (likely(!(ioflags & IO_INVIS))) |
672 | * We're not supposed to change timestamps in readonly-mounted | ||
673 | * filesystems. Throw it away if anyone asks us. | ||
674 | */ | ||
675 | if (likely(!(ioflags & IO_INVIS) && | ||
676 | !mnt_want_write(file->f_path.mnt))) { | ||
677 | xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 671 | xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
678 | mnt_drop_write(file->f_path.mnt); | ||
679 | } | ||
680 | 672 | ||
681 | /* | 673 | /* |
682 | * If the offset is beyond the size of the file, we have a couple | 674 | * If the offset is beyond the size of the file, we have a couple |
@@ -715,7 +707,6 @@ start: | |||
715 | } | 707 | } |
716 | } | 708 | } |
717 | 709 | ||
718 | retry: | ||
719 | /* We can write back this queue in page reclaim */ | 710 | /* We can write back this queue in page reclaim */ |
720 | current->backing_dev_info = mapping->backing_dev_info; | 711 | current->backing_dev_info = mapping->backing_dev_info; |
721 | 712 | ||
@@ -771,6 +762,17 @@ retry: | |||
771 | if (ret == -EIOCBQUEUED && !(ioflags & IO_ISAIO)) | 762 | if (ret == -EIOCBQUEUED && !(ioflags & IO_ISAIO)) |
772 | ret = wait_on_sync_kiocb(iocb); | 763 | ret = wait_on_sync_kiocb(iocb); |
773 | 764 | ||
765 | isize = i_size_read(inode); | ||
766 | if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize)) | ||
767 | *offset = isize; | ||
768 | |||
769 | if (*offset > xip->i_size) { | ||
770 | xfs_ilock(xip, XFS_ILOCK_EXCL); | ||
771 | if (*offset > xip->i_size) | ||
772 | xip->i_size = *offset; | ||
773 | xfs_iunlock(xip, XFS_ILOCK_EXCL); | ||
774 | } | ||
775 | |||
774 | if (ret == -ENOSPC && | 776 | if (ret == -ENOSPC && |
775 | DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) { | 777 | DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) { |
776 | xfs_iunlock(xip, iolock); | 778 | xfs_iunlock(xip, iolock); |
@@ -784,20 +786,7 @@ retry: | |||
784 | xfs_ilock(xip, iolock); | 786 | xfs_ilock(xip, iolock); |
785 | if (error) | 787 | if (error) |
786 | goto out_unlock_internal; | 788 | goto out_unlock_internal; |
787 | pos = xip->i_size; | 789 | goto start; |
788 | ret = 0; | ||
789 | goto retry; | ||
790 | } | ||
791 | |||
792 | isize = i_size_read(inode); | ||
793 | if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize)) | ||
794 | *offset = isize; | ||
795 | |||
796 | if (*offset > xip->i_size) { | ||
797 | xfs_ilock(xip, XFS_ILOCK_EXCL); | ||
798 | if (*offset > xip->i_size) | ||
799 | xip->i_size = *offset; | ||
800 | xfs_iunlock(xip, XFS_ILOCK_EXCL); | ||
801 | } | 790 | } |
802 | 791 | ||
803 | error = -ret; | 792 | error = -ret; |
@@ -855,13 +844,7 @@ retry: | |||
855 | int | 844 | int |
856 | xfs_bdstrat_cb(struct xfs_buf *bp) | 845 | xfs_bdstrat_cb(struct xfs_buf *bp) |
857 | { | 846 | { |
858 | xfs_mount_t *mp; | 847 | if (XFS_FORCED_SHUTDOWN(bp->b_mount)) { |
859 | |||
860 | mp = XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *); | ||
861 | if (!XFS_FORCED_SHUTDOWN(mp)) { | ||
862 | xfs_buf_iorequest(bp); | ||
863 | return 0; | ||
864 | } else { | ||
865 | xfs_buftrace("XFS__BDSTRAT IOERROR", bp); | 848 | xfs_buftrace("XFS__BDSTRAT IOERROR", bp); |
866 | /* | 849 | /* |
867 | * Metadata write that didn't get logged but | 850 | * Metadata write that didn't get logged but |
@@ -874,6 +857,9 @@ xfs_bdstrat_cb(struct xfs_buf *bp) | |||
874 | else | 857 | else |
875 | return (xfs_bioerror(bp)); | 858 | return (xfs_bioerror(bp)); |
876 | } | 859 | } |
860 | |||
861 | xfs_buf_iorequest(bp); | ||
862 | return 0; | ||
877 | } | 863 | } |
878 | 864 | ||
879 | /* | 865 | /* |
diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c index 3d5b67c075c7..c3526d445f6a 100644 --- a/fs/xfs/linux-2.6/xfs_stats.c +++ b/fs/xfs/linux-2.6/xfs_stats.c | |||
@@ -53,11 +53,15 @@ xfs_read_xfsstats( | |||
53 | { "icluster", XFSSTAT_END_INODE_CLUSTER }, | 53 | { "icluster", XFSSTAT_END_INODE_CLUSTER }, |
54 | { "vnodes", XFSSTAT_END_VNODE_OPS }, | 54 | { "vnodes", XFSSTAT_END_VNODE_OPS }, |
55 | { "buf", XFSSTAT_END_BUF }, | 55 | { "buf", XFSSTAT_END_BUF }, |
56 | { "abtb2", XFSSTAT_END_ABTB_V2 }, | ||
57 | { "abtc2", XFSSTAT_END_ABTC_V2 }, | ||
58 | { "bmbt2", XFSSTAT_END_BMBT_V2 }, | ||
59 | { "ibt2", XFSSTAT_END_IBT_V2 }, | ||
56 | }; | 60 | }; |
57 | 61 | ||
58 | /* Loop over all stats groups */ | 62 | /* Loop over all stats groups */ |
59 | for (i=j=len = 0; i < ARRAY_SIZE(xstats); i++) { | 63 | for (i=j=len = 0; i < ARRAY_SIZE(xstats); i++) { |
60 | len += sprintf(buffer + len, xstats[i].desc); | 64 | len += sprintf(buffer + len, "%s", xstats[i].desc); |
61 | /* inner loop does each group */ | 65 | /* inner loop does each group */ |
62 | while (j < xstats[i].endpoint) { | 66 | while (j < xstats[i].endpoint) { |
63 | val = 0; | 67 | val = 0; |
diff --git a/fs/xfs/linux-2.6/xfs_stats.h b/fs/xfs/linux-2.6/xfs_stats.h index e83820febc9f..736854b1ca1a 100644 --- a/fs/xfs/linux-2.6/xfs_stats.h +++ b/fs/xfs/linux-2.6/xfs_stats.h | |||
@@ -118,6 +118,71 @@ struct xfsstats { | |||
118 | __uint32_t xb_page_retries; | 118 | __uint32_t xb_page_retries; |
119 | __uint32_t xb_page_found; | 119 | __uint32_t xb_page_found; |
120 | __uint32_t xb_get_read; | 120 | __uint32_t xb_get_read; |
121 | /* Version 2 btree counters */ | ||
122 | #define XFSSTAT_END_ABTB_V2 (XFSSTAT_END_BUF+15) | ||
123 | __uint32_t xs_abtb_2_lookup; | ||
124 | __uint32_t xs_abtb_2_compare; | ||
125 | __uint32_t xs_abtb_2_insrec; | ||
126 | __uint32_t xs_abtb_2_delrec; | ||
127 | __uint32_t xs_abtb_2_newroot; | ||
128 | __uint32_t xs_abtb_2_killroot; | ||
129 | __uint32_t xs_abtb_2_increment; | ||
130 | __uint32_t xs_abtb_2_decrement; | ||
131 | __uint32_t xs_abtb_2_lshift; | ||
132 | __uint32_t xs_abtb_2_rshift; | ||
133 | __uint32_t xs_abtb_2_split; | ||
134 | __uint32_t xs_abtb_2_join; | ||
135 | __uint32_t xs_abtb_2_alloc; | ||
136 | __uint32_t xs_abtb_2_free; | ||
137 | __uint32_t xs_abtb_2_moves; | ||
138 | #define XFSSTAT_END_ABTC_V2 (XFSSTAT_END_ABTB_V2+15) | ||
139 | __uint32_t xs_abtc_2_lookup; | ||
140 | __uint32_t xs_abtc_2_compare; | ||
141 | __uint32_t xs_abtc_2_insrec; | ||
142 | __uint32_t xs_abtc_2_delrec; | ||
143 | __uint32_t xs_abtc_2_newroot; | ||
144 | __uint32_t xs_abtc_2_killroot; | ||
145 | __uint32_t xs_abtc_2_increment; | ||
146 | __uint32_t xs_abtc_2_decrement; | ||
147 | __uint32_t xs_abtc_2_lshift; | ||
148 | __uint32_t xs_abtc_2_rshift; | ||
149 | __uint32_t xs_abtc_2_split; | ||
150 | __uint32_t xs_abtc_2_join; | ||
151 | __uint32_t xs_abtc_2_alloc; | ||
152 | __uint32_t xs_abtc_2_free; | ||
153 | __uint32_t xs_abtc_2_moves; | ||
154 | #define XFSSTAT_END_BMBT_V2 (XFSSTAT_END_ABTC_V2+15) | ||
155 | __uint32_t xs_bmbt_2_lookup; | ||
156 | __uint32_t xs_bmbt_2_compare; | ||
157 | __uint32_t xs_bmbt_2_insrec; | ||
158 | __uint32_t xs_bmbt_2_delrec; | ||
159 | __uint32_t xs_bmbt_2_newroot; | ||
160 | __uint32_t xs_bmbt_2_killroot; | ||
161 | __uint32_t xs_bmbt_2_increment; | ||
162 | __uint32_t xs_bmbt_2_decrement; | ||
163 | __uint32_t xs_bmbt_2_lshift; | ||
164 | __uint32_t xs_bmbt_2_rshift; | ||
165 | __uint32_t xs_bmbt_2_split; | ||
166 | __uint32_t xs_bmbt_2_join; | ||
167 | __uint32_t xs_bmbt_2_alloc; | ||
168 | __uint32_t xs_bmbt_2_free; | ||
169 | __uint32_t xs_bmbt_2_moves; | ||
170 | #define XFSSTAT_END_IBT_V2 (XFSSTAT_END_BMBT_V2+15) | ||
171 | __uint32_t xs_ibt_2_lookup; | ||
172 | __uint32_t xs_ibt_2_compare; | ||
173 | __uint32_t xs_ibt_2_insrec; | ||
174 | __uint32_t xs_ibt_2_delrec; | ||
175 | __uint32_t xs_ibt_2_newroot; | ||
176 | __uint32_t xs_ibt_2_killroot; | ||
177 | __uint32_t xs_ibt_2_increment; | ||
178 | __uint32_t xs_ibt_2_decrement; | ||
179 | __uint32_t xs_ibt_2_lshift; | ||
180 | __uint32_t xs_ibt_2_rshift; | ||
181 | __uint32_t xs_ibt_2_split; | ||
182 | __uint32_t xs_ibt_2_join; | ||
183 | __uint32_t xs_ibt_2_alloc; | ||
184 | __uint32_t xs_ibt_2_free; | ||
185 | __uint32_t xs_ibt_2_moves; | ||
121 | /* Extra precision counters */ | 186 | /* Extra precision counters */ |
122 | __uint64_t xs_xstrat_bytes; | 187 | __uint64_t xs_xstrat_bytes; |
123 | __uint64_t xs_write_bytes; | 188 | __uint64_t xs_write_bytes; |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 37ebe36056eb..36f6cc703ef2 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include "xfs.h" | 18 | #include "xfs.h" |
19 | #include "xfs_bit.h" | 19 | #include "xfs_bit.h" |
20 | #include "xfs_log.h" | 20 | #include "xfs_log.h" |
21 | #include "xfs_clnt.h" | ||
22 | #include "xfs_inum.h" | 21 | #include "xfs_inum.h" |
23 | #include "xfs_trans.h" | 22 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 23 | #include "xfs_sb.h" |
@@ -36,6 +35,7 @@ | |||
36 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
38 | #include "xfs_btree.h" | 37 | #include "xfs_btree.h" |
38 | #include "xfs_btree_trace.h" | ||
39 | #include "xfs_ialloc.h" | 39 | #include "xfs_ialloc.h" |
40 | #include "xfs_bmap.h" | 40 | #include "xfs_bmap.h" |
41 | #include "xfs_rtalloc.h" | 41 | #include "xfs_rtalloc.h" |
@@ -48,7 +48,6 @@ | |||
48 | #include "xfs_buf_item.h" | 48 | #include "xfs_buf_item.h" |
49 | #include "xfs_utils.h" | 49 | #include "xfs_utils.h" |
50 | #include "xfs_vnodeops.h" | 50 | #include "xfs_vnodeops.h" |
51 | #include "xfs_vfsops.h" | ||
52 | #include "xfs_version.h" | 51 | #include "xfs_version.h" |
53 | #include "xfs_log_priv.h" | 52 | #include "xfs_log_priv.h" |
54 | #include "xfs_trans_priv.h" | 53 | #include "xfs_trans_priv.h" |
@@ -58,6 +57,7 @@ | |||
58 | #include "xfs_extfree_item.h" | 57 | #include "xfs_extfree_item.h" |
59 | #include "xfs_mru_cache.h" | 58 | #include "xfs_mru_cache.h" |
60 | #include "xfs_inode_item.h" | 59 | #include "xfs_inode_item.h" |
60 | #include "xfs_sync.h" | ||
61 | 61 | ||
62 | #include <linux/namei.h> | 62 | #include <linux/namei.h> |
63 | #include <linux/init.h> | 63 | #include <linux/init.h> |
@@ -70,36 +70,9 @@ | |||
70 | 70 | ||
71 | static struct quotactl_ops xfs_quotactl_operations; | 71 | static struct quotactl_ops xfs_quotactl_operations; |
72 | static struct super_operations xfs_super_operations; | 72 | static struct super_operations xfs_super_operations; |
73 | static kmem_zone_t *xfs_vnode_zone; | ||
74 | static kmem_zone_t *xfs_ioend_zone; | 73 | static kmem_zone_t *xfs_ioend_zone; |
75 | mempool_t *xfs_ioend_pool; | 74 | mempool_t *xfs_ioend_pool; |
76 | 75 | ||
77 | STATIC struct xfs_mount_args * | ||
78 | xfs_args_allocate( | ||
79 | struct super_block *sb, | ||
80 | int silent) | ||
81 | { | ||
82 | struct xfs_mount_args *args; | ||
83 | |||
84 | args = kzalloc(sizeof(struct xfs_mount_args), GFP_KERNEL); | ||
85 | if (!args) | ||
86 | return NULL; | ||
87 | |||
88 | args->logbufs = args->logbufsize = -1; | ||
89 | strncpy(args->fsname, sb->s_id, MAXNAMELEN); | ||
90 | |||
91 | /* Copy the already-parsed mount(2) flags we're interested in */ | ||
92 | if (sb->s_flags & MS_DIRSYNC) | ||
93 | args->flags |= XFSMNT_DIRSYNC; | ||
94 | if (sb->s_flags & MS_SYNCHRONOUS) | ||
95 | args->flags |= XFSMNT_WSYNC; | ||
96 | if (silent) | ||
97 | args->flags |= XFSMNT_QUIET; | ||
98 | args->flags |= XFSMNT_32BITINODES; | ||
99 | |||
100 | return args; | ||
101 | } | ||
102 | |||
103 | #define MNTOPT_LOGBUFS "logbufs" /* number of XFS log buffers */ | 76 | #define MNTOPT_LOGBUFS "logbufs" /* number of XFS log buffers */ |
104 | #define MNTOPT_LOGBSIZE "logbsize" /* size of XFS log buffers */ | 77 | #define MNTOPT_LOGBSIZE "logbsize" /* size of XFS log buffers */ |
105 | #define MNTOPT_LOGDEV "logdev" /* log device */ | 78 | #define MNTOPT_LOGDEV "logdev" /* log device */ |
@@ -188,26 +161,54 @@ suffix_strtoul(char *s, char **endp, unsigned int base) | |||
188 | return simple_strtoul((const char *)s, endp, base) << shift_left_factor; | 161 | return simple_strtoul((const char *)s, endp, base) << shift_left_factor; |
189 | } | 162 | } |
190 | 163 | ||
164 | /* | ||
165 | * This function fills in xfs_mount_t fields based on mount args. | ||
166 | * Note: the superblock has _not_ yet been read in. | ||
167 | * | ||
168 | * Note that this function leaks the various device name allocations on | ||
169 | * failure. The caller takes care of them. | ||
170 | */ | ||
191 | STATIC int | 171 | STATIC int |
192 | xfs_parseargs( | 172 | xfs_parseargs( |
193 | struct xfs_mount *mp, | 173 | struct xfs_mount *mp, |
194 | char *options, | 174 | char *options, |
195 | struct xfs_mount_args *args, | 175 | char **mtpt) |
196 | int update) | ||
197 | { | 176 | { |
177 | struct super_block *sb = mp->m_super; | ||
198 | char *this_char, *value, *eov; | 178 | char *this_char, *value, *eov; |
199 | int dsunit, dswidth, vol_dsunit, vol_dswidth; | 179 | int dsunit = 0; |
200 | int iosize; | 180 | int dswidth = 0; |
181 | int iosize = 0; | ||
201 | int dmapi_implies_ikeep = 1; | 182 | int dmapi_implies_ikeep = 1; |
183 | uchar_t iosizelog = 0; | ||
184 | |||
185 | /* | ||
186 | * Copy binary VFS mount flags we are interested in. | ||
187 | */ | ||
188 | if (sb->s_flags & MS_RDONLY) | ||
189 | mp->m_flags |= XFS_MOUNT_RDONLY; | ||
190 | if (sb->s_flags & MS_DIRSYNC) | ||
191 | mp->m_flags |= XFS_MOUNT_DIRSYNC; | ||
192 | if (sb->s_flags & MS_SYNCHRONOUS) | ||
193 | mp->m_flags |= XFS_MOUNT_WSYNC; | ||
194 | |||
195 | /* | ||
196 | * Set some default flags that could be cleared by the mount option | ||
197 | * parsing. | ||
198 | */ | ||
199 | mp->m_flags |= XFS_MOUNT_BARRIER; | ||
200 | mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; | ||
201 | mp->m_flags |= XFS_MOUNT_SMALL_INUMS; | ||
202 | 202 | ||
203 | args->flags |= XFSMNT_BARRIER; | 203 | /* |
204 | args->flags2 |= XFSMNT2_COMPAT_IOSIZE; | 204 | * These can be overridden by the mount option parsing. |
205 | */ | ||
206 | mp->m_logbufs = -1; | ||
207 | mp->m_logbsize = -1; | ||
205 | 208 | ||
206 | if (!options) | 209 | if (!options) |
207 | goto done; | 210 | goto done; |
208 | 211 | ||
209 | iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0; | ||
210 | |||
211 | while ((this_char = strsep(&options, ",")) != NULL) { | 212 | while ((this_char = strsep(&options, ",")) != NULL) { |
212 | if (!*this_char) | 213 | if (!*this_char) |
213 | continue; | 214 | continue; |
@@ -221,7 +222,7 @@ xfs_parseargs( | |||
221 | this_char); | 222 | this_char); |
222 | return EINVAL; | 223 | return EINVAL; |
223 | } | 224 | } |
224 | args->logbufs = simple_strtoul(value, &eov, 10); | 225 | mp->m_logbufs = simple_strtoul(value, &eov, 10); |
225 | } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { | 226 | } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { |
226 | if (!value || !*value) { | 227 | if (!value || !*value) { |
227 | cmn_err(CE_WARN, | 228 | cmn_err(CE_WARN, |
@@ -229,7 +230,7 @@ xfs_parseargs( | |||
229 | this_char); | 230 | this_char); |
230 | return EINVAL; | 231 | return EINVAL; |
231 | } | 232 | } |
232 | args->logbufsize = suffix_strtoul(value, &eov, 10); | 233 | mp->m_logbsize = suffix_strtoul(value, &eov, 10); |
233 | } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { | 234 | } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { |
234 | if (!value || !*value) { | 235 | if (!value || !*value) { |
235 | cmn_err(CE_WARN, | 236 | cmn_err(CE_WARN, |
@@ -237,7 +238,9 @@ xfs_parseargs( | |||
237 | this_char); | 238 | this_char); |
238 | return EINVAL; | 239 | return EINVAL; |
239 | } | 240 | } |
240 | strncpy(args->logname, value, MAXNAMELEN); | 241 | mp->m_logname = kstrndup(value, MAXNAMELEN, GFP_KERNEL); |
242 | if (!mp->m_logname) | ||
243 | return ENOMEM; | ||
241 | } else if (!strcmp(this_char, MNTOPT_MTPT)) { | 244 | } else if (!strcmp(this_char, MNTOPT_MTPT)) { |
242 | if (!value || !*value) { | 245 | if (!value || !*value) { |
243 | cmn_err(CE_WARN, | 246 | cmn_err(CE_WARN, |
@@ -245,7 +248,9 @@ xfs_parseargs( | |||
245 | this_char); | 248 | this_char); |
246 | return EINVAL; | 249 | return EINVAL; |
247 | } | 250 | } |
248 | strncpy(args->mtpt, value, MAXNAMELEN); | 251 | *mtpt = kstrndup(value, MAXNAMELEN, GFP_KERNEL); |
252 | if (!*mtpt) | ||
253 | return ENOMEM; | ||
249 | } else if (!strcmp(this_char, MNTOPT_RTDEV)) { | 254 | } else if (!strcmp(this_char, MNTOPT_RTDEV)) { |
250 | if (!value || !*value) { | 255 | if (!value || !*value) { |
251 | cmn_err(CE_WARN, | 256 | cmn_err(CE_WARN, |
@@ -253,7 +258,9 @@ xfs_parseargs( | |||
253 | this_char); | 258 | this_char); |
254 | return EINVAL; | 259 | return EINVAL; |
255 | } | 260 | } |
256 | strncpy(args->rtname, value, MAXNAMELEN); | 261 | mp->m_rtname = kstrndup(value, MAXNAMELEN, GFP_KERNEL); |
262 | if (!mp->m_rtname) | ||
263 | return ENOMEM; | ||
257 | } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { | 264 | } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { |
258 | if (!value || !*value) { | 265 | if (!value || !*value) { |
259 | cmn_err(CE_WARN, | 266 | cmn_err(CE_WARN, |
@@ -262,8 +269,7 @@ xfs_parseargs( | |||
262 | return EINVAL; | 269 | return EINVAL; |
263 | } | 270 | } |
264 | iosize = simple_strtoul(value, &eov, 10); | 271 | iosize = simple_strtoul(value, &eov, 10); |
265 | args->flags |= XFSMNT_IOSIZE; | 272 | iosizelog = ffs(iosize) - 1; |
266 | args->iosizelog = (uint8_t) iosize; | ||
267 | } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { | 273 | } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { |
268 | if (!value || !*value) { | 274 | if (!value || !*value) { |
269 | cmn_err(CE_WARN, | 275 | cmn_err(CE_WARN, |
@@ -272,8 +278,7 @@ xfs_parseargs( | |||
272 | return EINVAL; | 278 | return EINVAL; |
273 | } | 279 | } |
274 | iosize = suffix_strtoul(value, &eov, 10); | 280 | iosize = suffix_strtoul(value, &eov, 10); |
275 | args->flags |= XFSMNT_IOSIZE; | 281 | iosizelog = ffs(iosize) - 1; |
276 | args->iosizelog = ffs(iosize) - 1; | ||
277 | } else if (!strcmp(this_char, MNTOPT_GRPID) || | 282 | } else if (!strcmp(this_char, MNTOPT_GRPID) || |
278 | !strcmp(this_char, MNTOPT_BSDGROUPS)) { | 283 | !strcmp(this_char, MNTOPT_BSDGROUPS)) { |
279 | mp->m_flags |= XFS_MOUNT_GRPID; | 284 | mp->m_flags |= XFS_MOUNT_GRPID; |
@@ -281,23 +286,25 @@ xfs_parseargs( | |||
281 | !strcmp(this_char, MNTOPT_SYSVGROUPS)) { | 286 | !strcmp(this_char, MNTOPT_SYSVGROUPS)) { |
282 | mp->m_flags &= ~XFS_MOUNT_GRPID; | 287 | mp->m_flags &= ~XFS_MOUNT_GRPID; |
283 | } else if (!strcmp(this_char, MNTOPT_WSYNC)) { | 288 | } else if (!strcmp(this_char, MNTOPT_WSYNC)) { |
284 | args->flags |= XFSMNT_WSYNC; | 289 | mp->m_flags |= XFS_MOUNT_WSYNC; |
285 | } else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) { | 290 | } else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) { |
286 | args->flags |= XFSMNT_OSYNCISOSYNC; | 291 | mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC; |
287 | } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) { | 292 | } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) { |
288 | args->flags |= XFSMNT_NORECOVERY; | 293 | mp->m_flags |= XFS_MOUNT_NORECOVERY; |
289 | } else if (!strcmp(this_char, MNTOPT_INO64)) { | 294 | } else if (!strcmp(this_char, MNTOPT_INO64)) { |
290 | args->flags |= XFSMNT_INO64; | 295 | #if XFS_BIG_INUMS |
291 | #if !XFS_BIG_INUMS | 296 | mp->m_flags |= XFS_MOUNT_INO64; |
297 | mp->m_inoadd = XFS_INO64_OFFSET; | ||
298 | #else | ||
292 | cmn_err(CE_WARN, | 299 | cmn_err(CE_WARN, |
293 | "XFS: %s option not allowed on this system", | 300 | "XFS: %s option not allowed on this system", |
294 | this_char); | 301 | this_char); |
295 | return EINVAL; | 302 | return EINVAL; |
296 | #endif | 303 | #endif |
297 | } else if (!strcmp(this_char, MNTOPT_NOALIGN)) { | 304 | } else if (!strcmp(this_char, MNTOPT_NOALIGN)) { |
298 | args->flags |= XFSMNT_NOALIGN; | 305 | mp->m_flags |= XFS_MOUNT_NOALIGN; |
299 | } else if (!strcmp(this_char, MNTOPT_SWALLOC)) { | 306 | } else if (!strcmp(this_char, MNTOPT_SWALLOC)) { |
300 | args->flags |= XFSMNT_SWALLOC; | 307 | mp->m_flags |= XFS_MOUNT_SWALLOC; |
301 | } else if (!strcmp(this_char, MNTOPT_SUNIT)) { | 308 | } else if (!strcmp(this_char, MNTOPT_SUNIT)) { |
302 | if (!value || !*value) { | 309 | if (!value || !*value) { |
303 | cmn_err(CE_WARN, | 310 | cmn_err(CE_WARN, |
@@ -315,7 +322,7 @@ xfs_parseargs( | |||
315 | } | 322 | } |
316 | dswidth = simple_strtoul(value, &eov, 10); | 323 | dswidth = simple_strtoul(value, &eov, 10); |
317 | } else if (!strcmp(this_char, MNTOPT_64BITINODE)) { | 324 | } else if (!strcmp(this_char, MNTOPT_64BITINODE)) { |
318 | args->flags &= ~XFSMNT_32BITINODES; | 325 | mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS; |
319 | #if !XFS_BIG_INUMS | 326 | #if !XFS_BIG_INUMS |
320 | cmn_err(CE_WARN, | 327 | cmn_err(CE_WARN, |
321 | "XFS: %s option not allowed on this system", | 328 | "XFS: %s option not allowed on this system", |
@@ -323,56 +330,61 @@ xfs_parseargs( | |||
323 | return EINVAL; | 330 | return EINVAL; |
324 | #endif | 331 | #endif |
325 | } else if (!strcmp(this_char, MNTOPT_NOUUID)) { | 332 | } else if (!strcmp(this_char, MNTOPT_NOUUID)) { |
326 | args->flags |= XFSMNT_NOUUID; | 333 | mp->m_flags |= XFS_MOUNT_NOUUID; |
327 | } else if (!strcmp(this_char, MNTOPT_BARRIER)) { | 334 | } else if (!strcmp(this_char, MNTOPT_BARRIER)) { |
328 | args->flags |= XFSMNT_BARRIER; | 335 | mp->m_flags |= XFS_MOUNT_BARRIER; |
329 | } else if (!strcmp(this_char, MNTOPT_NOBARRIER)) { | 336 | } else if (!strcmp(this_char, MNTOPT_NOBARRIER)) { |
330 | args->flags &= ~XFSMNT_BARRIER; | 337 | mp->m_flags &= ~XFS_MOUNT_BARRIER; |
331 | } else if (!strcmp(this_char, MNTOPT_IKEEP)) { | 338 | } else if (!strcmp(this_char, MNTOPT_IKEEP)) { |
332 | args->flags |= XFSMNT_IKEEP; | 339 | mp->m_flags |= XFS_MOUNT_IKEEP; |
333 | } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) { | 340 | } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) { |
334 | dmapi_implies_ikeep = 0; | 341 | dmapi_implies_ikeep = 0; |
335 | args->flags &= ~XFSMNT_IKEEP; | 342 | mp->m_flags &= ~XFS_MOUNT_IKEEP; |
336 | } else if (!strcmp(this_char, MNTOPT_LARGEIO)) { | 343 | } else if (!strcmp(this_char, MNTOPT_LARGEIO)) { |
337 | args->flags2 &= ~XFSMNT2_COMPAT_IOSIZE; | 344 | mp->m_flags &= ~XFS_MOUNT_COMPAT_IOSIZE; |
338 | } else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) { | 345 | } else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) { |
339 | args->flags2 |= XFSMNT2_COMPAT_IOSIZE; | 346 | mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; |
340 | } else if (!strcmp(this_char, MNTOPT_ATTR2)) { | 347 | } else if (!strcmp(this_char, MNTOPT_ATTR2)) { |
341 | args->flags |= XFSMNT_ATTR2; | 348 | mp->m_flags |= XFS_MOUNT_ATTR2; |
342 | } else if (!strcmp(this_char, MNTOPT_NOATTR2)) { | 349 | } else if (!strcmp(this_char, MNTOPT_NOATTR2)) { |
343 | args->flags &= ~XFSMNT_ATTR2; | 350 | mp->m_flags &= ~XFS_MOUNT_ATTR2; |
344 | args->flags |= XFSMNT_NOATTR2; | 351 | mp->m_flags |= XFS_MOUNT_NOATTR2; |
345 | } else if (!strcmp(this_char, MNTOPT_FILESTREAM)) { | 352 | } else if (!strcmp(this_char, MNTOPT_FILESTREAM)) { |
346 | args->flags2 |= XFSMNT2_FILESTREAMS; | 353 | mp->m_flags |= XFS_MOUNT_FILESTREAMS; |
347 | } else if (!strcmp(this_char, MNTOPT_NOQUOTA)) { | 354 | } else if (!strcmp(this_char, MNTOPT_NOQUOTA)) { |
348 | args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA); | 355 | mp->m_qflags &= ~(XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE | |
349 | args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA); | 356 | XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE | |
357 | XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE | | ||
358 | XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD); | ||
350 | } else if (!strcmp(this_char, MNTOPT_QUOTA) || | 359 | } else if (!strcmp(this_char, MNTOPT_QUOTA) || |
351 | !strcmp(this_char, MNTOPT_UQUOTA) || | 360 | !strcmp(this_char, MNTOPT_UQUOTA) || |
352 | !strcmp(this_char, MNTOPT_USRQUOTA)) { | 361 | !strcmp(this_char, MNTOPT_USRQUOTA)) { |
353 | args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF; | 362 | mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE | |
363 | XFS_UQUOTA_ENFD); | ||
354 | } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) || | 364 | } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) || |
355 | !strcmp(this_char, MNTOPT_UQUOTANOENF)) { | 365 | !strcmp(this_char, MNTOPT_UQUOTANOENF)) { |
356 | args->flags |= XFSMNT_UQUOTA; | 366 | mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE); |
357 | args->flags &= ~XFSMNT_UQUOTAENF; | 367 | mp->m_qflags &= ~XFS_UQUOTA_ENFD; |
358 | } else if (!strcmp(this_char, MNTOPT_PQUOTA) || | 368 | } else if (!strcmp(this_char, MNTOPT_PQUOTA) || |
359 | !strcmp(this_char, MNTOPT_PRJQUOTA)) { | 369 | !strcmp(this_char, MNTOPT_PRJQUOTA)) { |
360 | args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF; | 370 | mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE | |
371 | XFS_OQUOTA_ENFD); | ||
361 | } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) { | 372 | } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) { |
362 | args->flags |= XFSMNT_PQUOTA; | 373 | mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE); |
363 | args->flags &= ~XFSMNT_PQUOTAENF; | 374 | mp->m_qflags &= ~XFS_OQUOTA_ENFD; |
364 | } else if (!strcmp(this_char, MNTOPT_GQUOTA) || | 375 | } else if (!strcmp(this_char, MNTOPT_GQUOTA) || |
365 | !strcmp(this_char, MNTOPT_GRPQUOTA)) { | 376 | !strcmp(this_char, MNTOPT_GRPQUOTA)) { |
366 | args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF; | 377 | mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE | |
378 | XFS_OQUOTA_ENFD); | ||
367 | } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) { | 379 | } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) { |
368 | args->flags |= XFSMNT_GQUOTA; | 380 | mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE); |
369 | args->flags &= ~XFSMNT_GQUOTAENF; | 381 | mp->m_qflags &= ~XFS_OQUOTA_ENFD; |
370 | } else if (!strcmp(this_char, MNTOPT_DMAPI)) { | 382 | } else if (!strcmp(this_char, MNTOPT_DMAPI)) { |
371 | args->flags |= XFSMNT_DMAPI; | 383 | mp->m_flags |= XFS_MOUNT_DMAPI; |
372 | } else if (!strcmp(this_char, MNTOPT_XDSM)) { | 384 | } else if (!strcmp(this_char, MNTOPT_XDSM)) { |
373 | args->flags |= XFSMNT_DMAPI; | 385 | mp->m_flags |= XFS_MOUNT_DMAPI; |
374 | } else if (!strcmp(this_char, MNTOPT_DMI)) { | 386 | } else if (!strcmp(this_char, MNTOPT_DMI)) { |
375 | args->flags |= XFSMNT_DMAPI; | 387 | mp->m_flags |= XFS_MOUNT_DMAPI; |
376 | } else if (!strcmp(this_char, "ihashsize")) { | 388 | } else if (!strcmp(this_char, "ihashsize")) { |
377 | cmn_err(CE_WARN, | 389 | cmn_err(CE_WARN, |
378 | "XFS: ihashsize no longer used, option is deprecated."); | 390 | "XFS: ihashsize no longer used, option is deprecated."); |
@@ -390,27 +402,29 @@ xfs_parseargs( | |||
390 | } | 402 | } |
391 | } | 403 | } |
392 | 404 | ||
393 | if (args->flags & XFSMNT_NORECOVERY) { | 405 | /* |
394 | if ((mp->m_flags & XFS_MOUNT_RDONLY) == 0) { | 406 | * no recovery flag requires a read-only mount |
395 | cmn_err(CE_WARN, | 407 | */ |
396 | "XFS: no-recovery mounts must be read-only."); | 408 | if ((mp->m_flags & XFS_MOUNT_NORECOVERY) && |
397 | return EINVAL; | 409 | !(mp->m_flags & XFS_MOUNT_RDONLY)) { |
398 | } | 410 | cmn_err(CE_WARN, "XFS: no-recovery mounts must be read-only."); |
411 | return EINVAL; | ||
399 | } | 412 | } |
400 | 413 | ||
401 | if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) { | 414 | if ((mp->m_flags & XFS_MOUNT_NOALIGN) && (dsunit || dswidth)) { |
402 | cmn_err(CE_WARN, | 415 | cmn_err(CE_WARN, |
403 | "XFS: sunit and swidth options incompatible with the noalign option"); | 416 | "XFS: sunit and swidth options incompatible with the noalign option"); |
404 | return EINVAL; | 417 | return EINVAL; |
405 | } | 418 | } |
406 | 419 | ||
407 | if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) { | 420 | if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) && |
421 | (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) { | ||
408 | cmn_err(CE_WARN, | 422 | cmn_err(CE_WARN, |
409 | "XFS: cannot mount with both project and group quota"); | 423 | "XFS: cannot mount with both project and group quota"); |
410 | return EINVAL; | 424 | return EINVAL; |
411 | } | 425 | } |
412 | 426 | ||
413 | if ((args->flags & XFSMNT_DMAPI) && *args->mtpt == '\0') { | 427 | if ((mp->m_flags & XFS_MOUNT_DMAPI) && (!*mtpt || *mtpt[0] == '\0')) { |
414 | printk("XFS: %s option needs the mount point option as well\n", | 428 | printk("XFS: %s option needs the mount point option as well\n", |
415 | MNTOPT_DMAPI); | 429 | MNTOPT_DMAPI); |
416 | return EINVAL; | 430 | return EINVAL; |
@@ -438,27 +452,66 @@ xfs_parseargs( | |||
438 | * Note that if "ikeep" or "noikeep" mount options are | 452 | * Note that if "ikeep" or "noikeep" mount options are |
439 | * supplied, then they are honored. | 453 | * supplied, then they are honored. |
440 | */ | 454 | */ |
441 | if ((args->flags & XFSMNT_DMAPI) && dmapi_implies_ikeep) | 455 | if ((mp->m_flags & XFS_MOUNT_DMAPI) && dmapi_implies_ikeep) |
442 | args->flags |= XFSMNT_IKEEP; | 456 | mp->m_flags |= XFS_MOUNT_IKEEP; |
443 | 457 | ||
444 | if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) { | 458 | done: |
459 | if (!(mp->m_flags & XFS_MOUNT_NOALIGN)) { | ||
460 | /* | ||
461 | * At this point the superblock has not been read | ||
462 | * in, therefore we do not know the block size. | ||
463 | * Before the mount call ends we will convert | ||
464 | * these to FSBs. | ||
465 | */ | ||
445 | if (dsunit) { | 466 | if (dsunit) { |
446 | args->sunit = dsunit; | 467 | mp->m_dalign = dsunit; |
447 | args->flags |= XFSMNT_RETERR; | 468 | mp->m_flags |= XFS_MOUNT_RETERR; |
448 | } else { | ||
449 | args->sunit = vol_dsunit; | ||
450 | } | 469 | } |
451 | dswidth ? (args->swidth = dswidth) : | 470 | |
452 | (args->swidth = vol_dswidth); | 471 | if (dswidth) |
453 | } else { | 472 | mp->m_swidth = dswidth; |
454 | args->sunit = args->swidth = 0; | 473 | } |
474 | |||
475 | if (mp->m_logbufs != -1 && | ||
476 | mp->m_logbufs != 0 && | ||
477 | (mp->m_logbufs < XLOG_MIN_ICLOGS || | ||
478 | mp->m_logbufs > XLOG_MAX_ICLOGS)) { | ||
479 | cmn_err(CE_WARN, | ||
480 | "XFS: invalid logbufs value: %d [not %d-%d]", | ||
481 | mp->m_logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS); | ||
482 | return XFS_ERROR(EINVAL); | ||
483 | } | ||
484 | if (mp->m_logbsize != -1 && | ||
485 | mp->m_logbsize != 0 && | ||
486 | (mp->m_logbsize < XLOG_MIN_RECORD_BSIZE || | ||
487 | mp->m_logbsize > XLOG_MAX_RECORD_BSIZE || | ||
488 | !is_power_of_2(mp->m_logbsize))) { | ||
489 | cmn_err(CE_WARN, | ||
490 | "XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]", | ||
491 | mp->m_logbsize); | ||
492 | return XFS_ERROR(EINVAL); | ||
493 | } | ||
494 | |||
495 | mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL); | ||
496 | if (!mp->m_fsname) | ||
497 | return ENOMEM; | ||
498 | mp->m_fsname_len = strlen(mp->m_fsname) + 1; | ||
499 | |||
500 | if (iosizelog) { | ||
501 | if (iosizelog > XFS_MAX_IO_LOG || | ||
502 | iosizelog < XFS_MIN_IO_LOG) { | ||
503 | cmn_err(CE_WARN, | ||
504 | "XFS: invalid log iosize: %d [not %d-%d]", | ||
505 | iosizelog, XFS_MIN_IO_LOG, | ||
506 | XFS_MAX_IO_LOG); | ||
507 | return XFS_ERROR(EINVAL); | ||
508 | } | ||
509 | |||
510 | mp->m_flags |= XFS_MOUNT_DFLT_IOSIZE; | ||
511 | mp->m_readio_log = iosizelog; | ||
512 | mp->m_writeio_log = iosizelog; | ||
455 | } | 513 | } |
456 | 514 | ||
457 | done: | ||
458 | if (args->flags & XFSMNT_32BITINODES) | ||
459 | mp->m_flags |= XFS_MOUNT_SMALL_INUMS; | ||
460 | if (args->flags2) | ||
461 | args->flags |= XFSMNT_FLAGS2; | ||
462 | return 0; | 515 | return 0; |
463 | } | 516 | } |
464 | 517 | ||
@@ -704,8 +757,7 @@ xfs_close_devices( | |||
704 | */ | 757 | */ |
705 | STATIC int | 758 | STATIC int |
706 | xfs_open_devices( | 759 | xfs_open_devices( |
707 | struct xfs_mount *mp, | 760 | struct xfs_mount *mp) |
708 | struct xfs_mount_args *args) | ||
709 | { | 761 | { |
710 | struct block_device *ddev = mp->m_super->s_bdev; | 762 | struct block_device *ddev = mp->m_super->s_bdev; |
711 | struct block_device *logdev = NULL, *rtdev = NULL; | 763 | struct block_device *logdev = NULL, *rtdev = NULL; |
@@ -714,14 +766,14 @@ xfs_open_devices( | |||
714 | /* | 766 | /* |
715 | * Open real time and log devices - order is important. | 767 | * Open real time and log devices - order is important. |
716 | */ | 768 | */ |
717 | if (args->logname[0]) { | 769 | if (mp->m_logname) { |
718 | error = xfs_blkdev_get(mp, args->logname, &logdev); | 770 | error = xfs_blkdev_get(mp, mp->m_logname, &logdev); |
719 | if (error) | 771 | if (error) |
720 | goto out; | 772 | goto out; |
721 | } | 773 | } |
722 | 774 | ||
723 | if (args->rtname[0]) { | 775 | if (mp->m_rtname) { |
724 | error = xfs_blkdev_get(mp, args->rtname, &rtdev); | 776 | error = xfs_blkdev_get(mp, mp->m_rtname, &rtdev); |
725 | if (error) | 777 | if (error) |
726 | goto out_close_logdev; | 778 | goto out_close_logdev; |
727 | 779 | ||
@@ -813,18 +865,18 @@ xfs_setup_devices( | |||
813 | */ | 865 | */ |
814 | void | 866 | void |
815 | xfsaild_wakeup( | 867 | xfsaild_wakeup( |
816 | xfs_mount_t *mp, | 868 | struct xfs_ail *ailp, |
817 | xfs_lsn_t threshold_lsn) | 869 | xfs_lsn_t threshold_lsn) |
818 | { | 870 | { |
819 | mp->m_ail.xa_target = threshold_lsn; | 871 | ailp->xa_target = threshold_lsn; |
820 | wake_up_process(mp->m_ail.xa_task); | 872 | wake_up_process(ailp->xa_task); |
821 | } | 873 | } |
822 | 874 | ||
823 | int | 875 | int |
824 | xfsaild( | 876 | xfsaild( |
825 | void *data) | 877 | void *data) |
826 | { | 878 | { |
827 | xfs_mount_t *mp = (xfs_mount_t *)data; | 879 | struct xfs_ail *ailp = data; |
828 | xfs_lsn_t last_pushed_lsn = 0; | 880 | xfs_lsn_t last_pushed_lsn = 0; |
829 | long tout = 0; | 881 | long tout = 0; |
830 | 882 | ||
@@ -836,11 +888,11 @@ xfsaild( | |||
836 | /* swsusp */ | 888 | /* swsusp */ |
837 | try_to_freeze(); | 889 | try_to_freeze(); |
838 | 890 | ||
839 | ASSERT(mp->m_log); | 891 | ASSERT(ailp->xa_mount->m_log); |
840 | if (XFS_FORCED_SHUTDOWN(mp)) | 892 | if (XFS_FORCED_SHUTDOWN(ailp->xa_mount)) |
841 | continue; | 893 | continue; |
842 | 894 | ||
843 | tout = xfsaild_push(mp, &last_pushed_lsn); | 895 | tout = xfsaild_push(ailp, &last_pushed_lsn); |
844 | } | 896 | } |
845 | 897 | ||
846 | return 0; | 898 | return 0; |
@@ -848,43 +900,82 @@ xfsaild( | |||
848 | 900 | ||
849 | int | 901 | int |
850 | xfsaild_start( | 902 | xfsaild_start( |
851 | xfs_mount_t *mp) | 903 | struct xfs_ail *ailp) |
852 | { | 904 | { |
853 | mp->m_ail.xa_target = 0; | 905 | ailp->xa_target = 0; |
854 | mp->m_ail.xa_task = kthread_run(xfsaild, mp, "xfsaild"); | 906 | ailp->xa_task = kthread_run(xfsaild, ailp, "xfsaild"); |
855 | if (IS_ERR(mp->m_ail.xa_task)) | 907 | if (IS_ERR(ailp->xa_task)) |
856 | return -PTR_ERR(mp->m_ail.xa_task); | 908 | return -PTR_ERR(ailp->xa_task); |
857 | return 0; | 909 | return 0; |
858 | } | 910 | } |
859 | 911 | ||
860 | void | 912 | void |
861 | xfsaild_stop( | 913 | xfsaild_stop( |
862 | xfs_mount_t *mp) | 914 | struct xfs_ail *ailp) |
863 | { | 915 | { |
864 | kthread_stop(mp->m_ail.xa_task); | 916 | kthread_stop(ailp->xa_task); |
865 | } | 917 | } |
866 | 918 | ||
867 | 919 | ||
868 | 920 | /* Catch misguided souls that try to use this interface on XFS */ | |
869 | STATIC struct inode * | 921 | STATIC struct inode * |
870 | xfs_fs_alloc_inode( | 922 | xfs_fs_alloc_inode( |
871 | struct super_block *sb) | 923 | struct super_block *sb) |
872 | { | 924 | { |
873 | return kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); | 925 | BUG(); |
926 | return NULL; | ||
874 | } | 927 | } |
875 | 928 | ||
929 | /* | ||
930 | * Now that the generic code is guaranteed not to be accessing | ||
931 | * the linux inode, we can reclaim the inode. | ||
932 | */ | ||
876 | STATIC void | 933 | STATIC void |
877 | xfs_fs_destroy_inode( | 934 | xfs_fs_destroy_inode( |
878 | struct inode *inode) | 935 | struct inode *inode) |
879 | { | 936 | { |
880 | kmem_zone_free(xfs_vnode_zone, inode); | 937 | xfs_inode_t *ip = XFS_I(inode); |
938 | |||
939 | XFS_STATS_INC(vn_reclaim); | ||
940 | if (xfs_reclaim(ip)) | ||
941 | panic("%s: cannot reclaim 0x%p\n", __func__, inode); | ||
881 | } | 942 | } |
882 | 943 | ||
944 | /* | ||
945 | * Slab object creation initialisation for the XFS inode. | ||
946 | * This covers only the idempotent fields in the XFS inode; | ||
947 | * all other fields need to be initialised on allocation | ||
948 | * from the slab. This avoids the need to repeatedly intialise | ||
949 | * fields in the xfs inode that left in the initialise state | ||
950 | * when freeing the inode. | ||
951 | */ | ||
883 | STATIC void | 952 | STATIC void |
884 | xfs_fs_inode_init_once( | 953 | xfs_fs_inode_init_once( |
885 | void *vnode) | 954 | void *inode) |
886 | { | 955 | { |
887 | inode_init_once((struct inode *)vnode); | 956 | struct xfs_inode *ip = inode; |
957 | |||
958 | memset(ip, 0, sizeof(struct xfs_inode)); | ||
959 | |||
960 | /* vfs inode */ | ||
961 | inode_init_once(VFS_I(ip)); | ||
962 | |||
963 | /* xfs inode */ | ||
964 | atomic_set(&ip->i_iocount, 0); | ||
965 | atomic_set(&ip->i_pincount, 0); | ||
966 | spin_lock_init(&ip->i_flags_lock); | ||
967 | init_waitqueue_head(&ip->i_ipin_wait); | ||
968 | /* | ||
969 | * Because we want to use a counting completion, complete | ||
970 | * the flush completion once to allow a single access to | ||
971 | * the flush completion without blocking. | ||
972 | */ | ||
973 | init_completion(&ip->i_flush); | ||
974 | complete(&ip->i_flush); | ||
975 | |||
976 | mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, | ||
977 | "xfsino", ip->i_ino); | ||
978 | mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); | ||
888 | } | 979 | } |
889 | 980 | ||
890 | /* | 981 | /* |
@@ -898,21 +989,26 @@ xfs_fs_write_inode( | |||
898 | struct inode *inode, | 989 | struct inode *inode, |
899 | int sync) | 990 | int sync) |
900 | { | 991 | { |
992 | struct xfs_inode *ip = XFS_I(inode); | ||
901 | int error = 0; | 993 | int error = 0; |
902 | int flags = 0; | 994 | int flags = 0; |
903 | 995 | ||
904 | xfs_itrace_entry(XFS_I(inode)); | 996 | xfs_itrace_entry(ip); |
905 | if (sync) { | 997 | if (sync) { |
906 | filemap_fdatawait(inode->i_mapping); | 998 | error = xfs_wait_on_pages(ip, 0, -1); |
999 | if (error) | ||
1000 | goto out_error; | ||
907 | flags |= FLUSH_SYNC; | 1001 | flags |= FLUSH_SYNC; |
908 | } | 1002 | } |
909 | error = xfs_inode_flush(XFS_I(inode), flags); | 1003 | error = xfs_inode_flush(ip, flags); |
1004 | |||
1005 | out_error: | ||
910 | /* | 1006 | /* |
911 | * if we failed to write out the inode then mark | 1007 | * if we failed to write out the inode then mark |
912 | * it dirty again so we'll try again later. | 1008 | * it dirty again so we'll try again later. |
913 | */ | 1009 | */ |
914 | if (error) | 1010 | if (error) |
915 | mark_inode_dirty_sync(inode); | 1011 | xfs_mark_inode_dirty_sync(ip); |
916 | 1012 | ||
917 | return -error; | 1013 | return -error; |
918 | } | 1014 | } |
@@ -923,164 +1019,12 @@ xfs_fs_clear_inode( | |||
923 | { | 1019 | { |
924 | xfs_inode_t *ip = XFS_I(inode); | 1020 | xfs_inode_t *ip = XFS_I(inode); |
925 | 1021 | ||
926 | /* | 1022 | xfs_itrace_entry(ip); |
927 | * ip can be null when xfs_iget_core calls xfs_idestroy if we | 1023 | XFS_STATS_INC(vn_rele); |
928 | * find an inode with di_mode == 0 but without IGET_CREATE set. | 1024 | XFS_STATS_INC(vn_remove); |
929 | */ | 1025 | XFS_STATS_DEC(vn_active); |
930 | if (ip) { | ||
931 | xfs_itrace_entry(ip); | ||
932 | XFS_STATS_INC(vn_rele); | ||
933 | XFS_STATS_INC(vn_remove); | ||
934 | XFS_STATS_INC(vn_reclaim); | ||
935 | XFS_STATS_DEC(vn_active); | ||
936 | |||
937 | xfs_inactive(ip); | ||
938 | xfs_iflags_clear(ip, XFS_IMODIFIED); | ||
939 | if (xfs_reclaim(ip)) | ||
940 | panic("%s: cannot reclaim 0x%p\n", __func__, inode); | ||
941 | } | ||
942 | |||
943 | ASSERT(XFS_I(inode) == NULL); | ||
944 | } | ||
945 | 1026 | ||
946 | /* | 1027 | xfs_inactive(ip); |
947 | * Enqueue a work item to be picked up by the vfs xfssyncd thread. | ||
948 | * Doing this has two advantages: | ||
949 | * - It saves on stack space, which is tight in certain situations | ||
950 | * - It can be used (with care) as a mechanism to avoid deadlocks. | ||
951 | * Flushing while allocating in a full filesystem requires both. | ||
952 | */ | ||
953 | STATIC void | ||
954 | xfs_syncd_queue_work( | ||
955 | struct xfs_mount *mp, | ||
956 | void *data, | ||
957 | void (*syncer)(struct xfs_mount *, void *)) | ||
958 | { | ||
959 | struct bhv_vfs_sync_work *work; | ||
960 | |||
961 | work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP); | ||
962 | INIT_LIST_HEAD(&work->w_list); | ||
963 | work->w_syncer = syncer; | ||
964 | work->w_data = data; | ||
965 | work->w_mount = mp; | ||
966 | spin_lock(&mp->m_sync_lock); | ||
967 | list_add_tail(&work->w_list, &mp->m_sync_list); | ||
968 | spin_unlock(&mp->m_sync_lock); | ||
969 | wake_up_process(mp->m_sync_task); | ||
970 | } | ||
971 | |||
972 | /* | ||
973 | * Flush delayed allocate data, attempting to free up reserved space | ||
974 | * from existing allocations. At this point a new allocation attempt | ||
975 | * has failed with ENOSPC and we are in the process of scratching our | ||
976 | * heads, looking about for more room... | ||
977 | */ | ||
978 | STATIC void | ||
979 | xfs_flush_inode_work( | ||
980 | struct xfs_mount *mp, | ||
981 | void *arg) | ||
982 | { | ||
983 | struct inode *inode = arg; | ||
984 | filemap_flush(inode->i_mapping); | ||
985 | iput(inode); | ||
986 | } | ||
987 | |||
988 | void | ||
989 | xfs_flush_inode( | ||
990 | xfs_inode_t *ip) | ||
991 | { | ||
992 | struct inode *inode = VFS_I(ip); | ||
993 | |||
994 | igrab(inode); | ||
995 | xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work); | ||
996 | delay(msecs_to_jiffies(500)); | ||
997 | } | ||
998 | |||
999 | /* | ||
1000 | * This is the "bigger hammer" version of xfs_flush_inode_work... | ||
1001 | * (IOW, "If at first you don't succeed, use a Bigger Hammer"). | ||
1002 | */ | ||
1003 | STATIC void | ||
1004 | xfs_flush_device_work( | ||
1005 | struct xfs_mount *mp, | ||
1006 | void *arg) | ||
1007 | { | ||
1008 | struct inode *inode = arg; | ||
1009 | sync_blockdev(mp->m_super->s_bdev); | ||
1010 | iput(inode); | ||
1011 | } | ||
1012 | |||
1013 | void | ||
1014 | xfs_flush_device( | ||
1015 | xfs_inode_t *ip) | ||
1016 | { | ||
1017 | struct inode *inode = VFS_I(ip); | ||
1018 | |||
1019 | igrab(inode); | ||
1020 | xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work); | ||
1021 | delay(msecs_to_jiffies(500)); | ||
1022 | xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); | ||
1023 | } | ||
1024 | |||
1025 | STATIC void | ||
1026 | xfs_sync_worker( | ||
1027 | struct xfs_mount *mp, | ||
1028 | void *unused) | ||
1029 | { | ||
1030 | int error; | ||
1031 | |||
1032 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) | ||
1033 | error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR); | ||
1034 | mp->m_sync_seq++; | ||
1035 | wake_up(&mp->m_wait_single_sync_task); | ||
1036 | } | ||
1037 | |||
1038 | STATIC int | ||
1039 | xfssyncd( | ||
1040 | void *arg) | ||
1041 | { | ||
1042 | struct xfs_mount *mp = arg; | ||
1043 | long timeleft; | ||
1044 | bhv_vfs_sync_work_t *work, *n; | ||
1045 | LIST_HEAD (tmp); | ||
1046 | |||
1047 | set_freezable(); | ||
1048 | timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10); | ||
1049 | for (;;) { | ||
1050 | timeleft = schedule_timeout_interruptible(timeleft); | ||
1051 | /* swsusp */ | ||
1052 | try_to_freeze(); | ||
1053 | if (kthread_should_stop() && list_empty(&mp->m_sync_list)) | ||
1054 | break; | ||
1055 | |||
1056 | spin_lock(&mp->m_sync_lock); | ||
1057 | /* | ||
1058 | * We can get woken by laptop mode, to do a sync - | ||
1059 | * that's the (only!) case where the list would be | ||
1060 | * empty with time remaining. | ||
1061 | */ | ||
1062 | if (!timeleft || list_empty(&mp->m_sync_list)) { | ||
1063 | if (!timeleft) | ||
1064 | timeleft = xfs_syncd_centisecs * | ||
1065 | msecs_to_jiffies(10); | ||
1066 | INIT_LIST_HEAD(&mp->m_sync_work.w_list); | ||
1067 | list_add_tail(&mp->m_sync_work.w_list, | ||
1068 | &mp->m_sync_list); | ||
1069 | } | ||
1070 | list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list) | ||
1071 | list_move(&work->w_list, &tmp); | ||
1072 | spin_unlock(&mp->m_sync_lock); | ||
1073 | |||
1074 | list_for_each_entry_safe(work, n, &tmp, w_list) { | ||
1075 | (*work->w_syncer)(mp, work->w_data); | ||
1076 | list_del(&work->w_list); | ||
1077 | if (work == &mp->m_sync_work) | ||
1078 | continue; | ||
1079 | kmem_free(work); | ||
1080 | } | ||
1081 | } | ||
1082 | |||
1083 | return 0; | ||
1084 | } | 1028 | } |
1085 | 1029 | ||
1086 | STATIC void | 1030 | STATIC void |
@@ -1099,11 +1043,9 @@ xfs_fs_put_super( | |||
1099 | struct xfs_mount *mp = XFS_M(sb); | 1043 | struct xfs_mount *mp = XFS_M(sb); |
1100 | struct xfs_inode *rip = mp->m_rootip; | 1044 | struct xfs_inode *rip = mp->m_rootip; |
1101 | int unmount_event_flags = 0; | 1045 | int unmount_event_flags = 0; |
1102 | int error; | ||
1103 | 1046 | ||
1104 | kthread_stop(mp->m_sync_task); | 1047 | xfs_syncd_stop(mp); |
1105 | 1048 | xfs_sync_inodes(mp, SYNC_ATTR|SYNC_DELWRI); | |
1106 | xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI); | ||
1107 | 1049 | ||
1108 | #ifdef HAVE_DMAPI | 1050 | #ifdef HAVE_DMAPI |
1109 | if (mp->m_flags & XFS_MOUNT_DMAPI) { | 1051 | if (mp->m_flags & XFS_MOUNT_DMAPI) { |
@@ -1128,18 +1070,6 @@ xfs_fs_put_super( | |||
1128 | xfs_filestream_unmount(mp); | 1070 | xfs_filestream_unmount(mp); |
1129 | 1071 | ||
1130 | XFS_bflush(mp->m_ddev_targp); | 1072 | XFS_bflush(mp->m_ddev_targp); |
1131 | error = xfs_unmount_flush(mp, 0); | ||
1132 | WARN_ON(error); | ||
1133 | |||
1134 | /* | ||
1135 | * If we're forcing a shutdown, typically because of a media error, | ||
1136 | * we want to make sure we invalidate dirty pages that belong to | ||
1137 | * referenced vnodes as well. | ||
1138 | */ | ||
1139 | if (XFS_FORCED_SHUTDOWN(mp)) { | ||
1140 | error = xfs_sync(mp, SYNC_WAIT | SYNC_CLOSE); | ||
1141 | ASSERT(error != EFSCORRUPTED); | ||
1142 | } | ||
1143 | 1073 | ||
1144 | if (mp->m_flags & XFS_MOUNT_DMAPI) { | 1074 | if (mp->m_flags & XFS_MOUNT_DMAPI) { |
1145 | XFS_SEND_UNMOUNT(mp, rip, DM_RIGHT_NULL, 0, 0, | 1075 | XFS_SEND_UNMOUNT(mp, rip, DM_RIGHT_NULL, 0, 0, |
@@ -1161,7 +1091,7 @@ xfs_fs_write_super( | |||
1161 | struct super_block *sb) | 1091 | struct super_block *sb) |
1162 | { | 1092 | { |
1163 | if (!(sb->s_flags & MS_RDONLY)) | 1093 | if (!(sb->s_flags & MS_RDONLY)) |
1164 | xfs_sync(XFS_M(sb), SYNC_FSDATA); | 1094 | xfs_sync_fsdata(XFS_M(sb), 0); |
1165 | sb->s_dirt = 0; | 1095 | sb->s_dirt = 0; |
1166 | } | 1096 | } |
1167 | 1097 | ||
@@ -1172,7 +1102,6 @@ xfs_fs_sync_super( | |||
1172 | { | 1102 | { |
1173 | struct xfs_mount *mp = XFS_M(sb); | 1103 | struct xfs_mount *mp = XFS_M(sb); |
1174 | int error; | 1104 | int error; |
1175 | int flags; | ||
1176 | 1105 | ||
1177 | /* | 1106 | /* |
1178 | * Treat a sync operation like a freeze. This is to work | 1107 | * Treat a sync operation like a freeze. This is to work |
@@ -1186,20 +1115,10 @@ xfs_fs_sync_super( | |||
1186 | * dirty the Linux inode until after the transaction I/O | 1115 | * dirty the Linux inode until after the transaction I/O |
1187 | * completes. | 1116 | * completes. |
1188 | */ | 1117 | */ |
1189 | if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) { | 1118 | if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) |
1190 | /* | 1119 | error = xfs_quiesce_data(mp); |
1191 | * First stage of freeze - no more writers will make progress | 1120 | else |
1192 | * now we are here, so we flush delwri and delalloc buffers | 1121 | error = xfs_sync_fsdata(mp, 0); |
1193 | * here, then wait for all I/O to complete. Data is frozen at | ||
1194 | * that point. Metadata is not frozen, transactions can still | ||
1195 | * occur here so don't bother flushing the buftarg (i.e | ||
1196 | * SYNC_QUIESCE) because it'll just get dirty again. | ||
1197 | */ | ||
1198 | flags = SYNC_DATA_QUIESCE; | ||
1199 | } else | ||
1200 | flags = SYNC_FSDATA; | ||
1201 | |||
1202 | error = xfs_sync(mp, flags); | ||
1203 | sb->s_dirt = 0; | 1122 | sb->s_dirt = 0; |
1204 | 1123 | ||
1205 | if (unlikely(laptop_mode)) { | 1124 | if (unlikely(laptop_mode)) { |
@@ -1337,9 +1256,8 @@ xfs_fs_remount( | |||
1337 | 1256 | ||
1338 | /* rw -> ro */ | 1257 | /* rw -> ro */ |
1339 | if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) { | 1258 | if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) { |
1340 | xfs_filestream_flush(mp); | 1259 | xfs_quiesce_data(mp); |
1341 | xfs_sync(mp, SYNC_DATA_QUIESCE); | 1260 | xfs_quiesce_attr(mp); |
1342 | xfs_attr_quiesce(mp); | ||
1343 | mp->m_flags |= XFS_MOUNT_RDONLY; | 1261 | mp->m_flags |= XFS_MOUNT_RDONLY; |
1344 | } | 1262 | } |
1345 | 1263 | ||
@@ -1348,7 +1266,7 @@ xfs_fs_remount( | |||
1348 | 1266 | ||
1349 | /* | 1267 | /* |
1350 | * Second stage of a freeze. The data is already frozen so we only | 1268 | * Second stage of a freeze. The data is already frozen so we only |
1351 | * need to take care of themetadata. Once that's done write a dummy | 1269 | * need to take care of the metadata. Once that's done write a dummy |
1352 | * record to dirty the log in case of a crash while frozen. | 1270 | * record to dirty the log in case of a crash while frozen. |
1353 | */ | 1271 | */ |
1354 | STATIC void | 1272 | STATIC void |
@@ -1357,7 +1275,7 @@ xfs_fs_lockfs( | |||
1357 | { | 1275 | { |
1358 | struct xfs_mount *mp = XFS_M(sb); | 1276 | struct xfs_mount *mp = XFS_M(sb); |
1359 | 1277 | ||
1360 | xfs_attr_quiesce(mp); | 1278 | xfs_quiesce_attr(mp); |
1361 | xfs_fs_log_dummy(mp); | 1279 | xfs_fs_log_dummy(mp); |
1362 | } | 1280 | } |
1363 | 1281 | ||
@@ -1422,175 +1340,28 @@ xfs_fs_setxquota( | |||
1422 | 1340 | ||
1423 | /* | 1341 | /* |
1424 | * This function fills in xfs_mount_t fields based on mount args. | 1342 | * This function fills in xfs_mount_t fields based on mount args. |
1425 | * Note: the superblock has _not_ yet been read in. | ||
1426 | */ | ||
1427 | STATIC int | ||
1428 | xfs_start_flags( | ||
1429 | struct xfs_mount_args *ap, | ||
1430 | struct xfs_mount *mp) | ||
1431 | { | ||
1432 | int error; | ||
1433 | |||
1434 | /* Values are in BBs */ | ||
1435 | if ((ap->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) { | ||
1436 | /* | ||
1437 | * At this point the superblock has not been read | ||
1438 | * in, therefore we do not know the block size. | ||
1439 | * Before the mount call ends we will convert | ||
1440 | * these to FSBs. | ||
1441 | */ | ||
1442 | mp->m_dalign = ap->sunit; | ||
1443 | mp->m_swidth = ap->swidth; | ||
1444 | } | ||
1445 | |||
1446 | if (ap->logbufs != -1 && | ||
1447 | ap->logbufs != 0 && | ||
1448 | (ap->logbufs < XLOG_MIN_ICLOGS || | ||
1449 | ap->logbufs > XLOG_MAX_ICLOGS)) { | ||
1450 | cmn_err(CE_WARN, | ||
1451 | "XFS: invalid logbufs value: %d [not %d-%d]", | ||
1452 | ap->logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS); | ||
1453 | return XFS_ERROR(EINVAL); | ||
1454 | } | ||
1455 | mp->m_logbufs = ap->logbufs; | ||
1456 | if (ap->logbufsize != -1 && | ||
1457 | ap->logbufsize != 0 && | ||
1458 | (ap->logbufsize < XLOG_MIN_RECORD_BSIZE || | ||
1459 | ap->logbufsize > XLOG_MAX_RECORD_BSIZE || | ||
1460 | !is_power_of_2(ap->logbufsize))) { | ||
1461 | cmn_err(CE_WARN, | ||
1462 | "XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]", | ||
1463 | ap->logbufsize); | ||
1464 | return XFS_ERROR(EINVAL); | ||
1465 | } | ||
1466 | |||
1467 | error = ENOMEM; | ||
1468 | |||
1469 | mp->m_logbsize = ap->logbufsize; | ||
1470 | mp->m_fsname_len = strlen(ap->fsname) + 1; | ||
1471 | |||
1472 | mp->m_fsname = kstrdup(ap->fsname, GFP_KERNEL); | ||
1473 | if (!mp->m_fsname) | ||
1474 | goto out; | ||
1475 | |||
1476 | if (ap->rtname[0]) { | ||
1477 | mp->m_rtname = kstrdup(ap->rtname, GFP_KERNEL); | ||
1478 | if (!mp->m_rtname) | ||
1479 | goto out_free_fsname; | ||
1480 | |||
1481 | } | ||
1482 | |||
1483 | if (ap->logname[0]) { | ||
1484 | mp->m_logname = kstrdup(ap->logname, GFP_KERNEL); | ||
1485 | if (!mp->m_logname) | ||
1486 | goto out_free_rtname; | ||
1487 | } | ||
1488 | |||
1489 | if (ap->flags & XFSMNT_WSYNC) | ||
1490 | mp->m_flags |= XFS_MOUNT_WSYNC; | ||
1491 | #if XFS_BIG_INUMS | ||
1492 | if (ap->flags & XFSMNT_INO64) { | ||
1493 | mp->m_flags |= XFS_MOUNT_INO64; | ||
1494 | mp->m_inoadd = XFS_INO64_OFFSET; | ||
1495 | } | ||
1496 | #endif | ||
1497 | if (ap->flags & XFSMNT_RETERR) | ||
1498 | mp->m_flags |= XFS_MOUNT_RETERR; | ||
1499 | if (ap->flags & XFSMNT_NOALIGN) | ||
1500 | mp->m_flags |= XFS_MOUNT_NOALIGN; | ||
1501 | if (ap->flags & XFSMNT_SWALLOC) | ||
1502 | mp->m_flags |= XFS_MOUNT_SWALLOC; | ||
1503 | if (ap->flags & XFSMNT_OSYNCISOSYNC) | ||
1504 | mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC; | ||
1505 | if (ap->flags & XFSMNT_32BITINODES) | ||
1506 | mp->m_flags |= XFS_MOUNT_32BITINODES; | ||
1507 | |||
1508 | if (ap->flags & XFSMNT_IOSIZE) { | ||
1509 | if (ap->iosizelog > XFS_MAX_IO_LOG || | ||
1510 | ap->iosizelog < XFS_MIN_IO_LOG) { | ||
1511 | cmn_err(CE_WARN, | ||
1512 | "XFS: invalid log iosize: %d [not %d-%d]", | ||
1513 | ap->iosizelog, XFS_MIN_IO_LOG, | ||
1514 | XFS_MAX_IO_LOG); | ||
1515 | return XFS_ERROR(EINVAL); | ||
1516 | } | ||
1517 | |||
1518 | mp->m_flags |= XFS_MOUNT_DFLT_IOSIZE; | ||
1519 | mp->m_readio_log = mp->m_writeio_log = ap->iosizelog; | ||
1520 | } | ||
1521 | |||
1522 | if (ap->flags & XFSMNT_IKEEP) | ||
1523 | mp->m_flags |= XFS_MOUNT_IKEEP; | ||
1524 | if (ap->flags & XFSMNT_DIRSYNC) | ||
1525 | mp->m_flags |= XFS_MOUNT_DIRSYNC; | ||
1526 | if (ap->flags & XFSMNT_ATTR2) | ||
1527 | mp->m_flags |= XFS_MOUNT_ATTR2; | ||
1528 | if (ap->flags & XFSMNT_NOATTR2) | ||
1529 | mp->m_flags |= XFS_MOUNT_NOATTR2; | ||
1530 | |||
1531 | if (ap->flags2 & XFSMNT2_COMPAT_IOSIZE) | ||
1532 | mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; | ||
1533 | |||
1534 | /* | ||
1535 | * no recovery flag requires a read-only mount | ||
1536 | */ | ||
1537 | if (ap->flags & XFSMNT_NORECOVERY) { | ||
1538 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { | ||
1539 | cmn_err(CE_WARN, | ||
1540 | "XFS: tried to mount a FS read-write without recovery!"); | ||
1541 | return XFS_ERROR(EINVAL); | ||
1542 | } | ||
1543 | mp->m_flags |= XFS_MOUNT_NORECOVERY; | ||
1544 | } | ||
1545 | |||
1546 | if (ap->flags & XFSMNT_NOUUID) | ||
1547 | mp->m_flags |= XFS_MOUNT_NOUUID; | ||
1548 | if (ap->flags & XFSMNT_BARRIER) | ||
1549 | mp->m_flags |= XFS_MOUNT_BARRIER; | ||
1550 | else | ||
1551 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | ||
1552 | |||
1553 | if (ap->flags2 & XFSMNT2_FILESTREAMS) | ||
1554 | mp->m_flags |= XFS_MOUNT_FILESTREAMS; | ||
1555 | |||
1556 | if (ap->flags & XFSMNT_DMAPI) | ||
1557 | mp->m_flags |= XFS_MOUNT_DMAPI; | ||
1558 | return 0; | ||
1559 | |||
1560 | |||
1561 | out_free_rtname: | ||
1562 | kfree(mp->m_rtname); | ||
1563 | out_free_fsname: | ||
1564 | kfree(mp->m_fsname); | ||
1565 | out: | ||
1566 | return error; | ||
1567 | } | ||
1568 | |||
1569 | /* | ||
1570 | * This function fills in xfs_mount_t fields based on mount args. | ||
1571 | * Note: the superblock _has_ now been read in. | 1343 | * Note: the superblock _has_ now been read in. |
1572 | */ | 1344 | */ |
1573 | STATIC int | 1345 | STATIC int |
1574 | xfs_finish_flags( | 1346 | xfs_finish_flags( |
1575 | struct xfs_mount_args *ap, | ||
1576 | struct xfs_mount *mp) | 1347 | struct xfs_mount *mp) |
1577 | { | 1348 | { |
1578 | int ronly = (mp->m_flags & XFS_MOUNT_RDONLY); | 1349 | int ronly = (mp->m_flags & XFS_MOUNT_RDONLY); |
1579 | 1350 | ||
1580 | /* Fail a mount where the logbuf is smaller then the log stripe */ | 1351 | /* Fail a mount where the logbuf is smaller then the log stripe */ |
1581 | if (xfs_sb_version_haslogv2(&mp->m_sb)) { | 1352 | if (xfs_sb_version_haslogv2(&mp->m_sb)) { |
1582 | if ((ap->logbufsize <= 0) && | 1353 | if (mp->m_logbsize <= 0 && |
1583 | (mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE)) { | 1354 | mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE) { |
1584 | mp->m_logbsize = mp->m_sb.sb_logsunit; | 1355 | mp->m_logbsize = mp->m_sb.sb_logsunit; |
1585 | } else if (ap->logbufsize > 0 && | 1356 | } else if (mp->m_logbsize > 0 && |
1586 | ap->logbufsize < mp->m_sb.sb_logsunit) { | 1357 | mp->m_logbsize < mp->m_sb.sb_logsunit) { |
1587 | cmn_err(CE_WARN, | 1358 | cmn_err(CE_WARN, |
1588 | "XFS: logbuf size must be greater than or equal to log stripe size"); | 1359 | "XFS: logbuf size must be greater than or equal to log stripe size"); |
1589 | return XFS_ERROR(EINVAL); | 1360 | return XFS_ERROR(EINVAL); |
1590 | } | 1361 | } |
1591 | } else { | 1362 | } else { |
1592 | /* Fail a mount if the logbuf is larger than 32K */ | 1363 | /* Fail a mount if the logbuf is larger than 32K */ |
1593 | if (ap->logbufsize > XLOG_BIG_RECORD_BSIZE) { | 1364 | if (mp->m_logbsize > XLOG_BIG_RECORD_BSIZE) { |
1594 | cmn_err(CE_WARN, | 1365 | cmn_err(CE_WARN, |
1595 | "XFS: logbuf size for version 1 logs must be 16K or 32K"); | 1366 | "XFS: logbuf size for version 1 logs must be 16K or 32K"); |
1596 | return XFS_ERROR(EINVAL); | 1367 | return XFS_ERROR(EINVAL); |
@@ -1602,7 +1373,7 @@ xfs_finish_flags( | |||
1602 | * told by noattr2 to turn it off | 1373 | * told by noattr2 to turn it off |
1603 | */ | 1374 | */ |
1604 | if (xfs_sb_version_hasattr2(&mp->m_sb) && | 1375 | if (xfs_sb_version_hasattr2(&mp->m_sb) && |
1605 | !(ap->flags & XFSMNT_NOATTR2)) | 1376 | !(mp->m_flags & XFS_MOUNT_NOATTR2)) |
1606 | mp->m_flags |= XFS_MOUNT_ATTR2; | 1377 | mp->m_flags |= XFS_MOUNT_ATTR2; |
1607 | 1378 | ||
1608 | /* | 1379 | /* |
@@ -1614,48 +1385,6 @@ xfs_finish_flags( | |||
1614 | return XFS_ERROR(EROFS); | 1385 | return XFS_ERROR(EROFS); |
1615 | } | 1386 | } |
1616 | 1387 | ||
1617 | /* | ||
1618 | * check for shared mount. | ||
1619 | */ | ||
1620 | if (ap->flags & XFSMNT_SHARED) { | ||
1621 | if (!xfs_sb_version_hasshared(&mp->m_sb)) | ||
1622 | return XFS_ERROR(EINVAL); | ||
1623 | |||
1624 | /* | ||
1625 | * For IRIX 6.5, shared mounts must have the shared | ||
1626 | * version bit set, have the persistent readonly | ||
1627 | * field set, must be version 0 and can only be mounted | ||
1628 | * read-only. | ||
1629 | */ | ||
1630 | if (!ronly || !(mp->m_sb.sb_flags & XFS_SBF_READONLY) || | ||
1631 | (mp->m_sb.sb_shared_vn != 0)) | ||
1632 | return XFS_ERROR(EINVAL); | ||
1633 | |||
1634 | mp->m_flags |= XFS_MOUNT_SHARED; | ||
1635 | |||
1636 | /* | ||
1637 | * Shared XFS V0 can't deal with DMI. Return EINVAL. | ||
1638 | */ | ||
1639 | if (mp->m_sb.sb_shared_vn == 0 && (ap->flags & XFSMNT_DMAPI)) | ||
1640 | return XFS_ERROR(EINVAL); | ||
1641 | } | ||
1642 | |||
1643 | if (ap->flags & XFSMNT_UQUOTA) { | ||
1644 | mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE); | ||
1645 | if (ap->flags & XFSMNT_UQUOTAENF) | ||
1646 | mp->m_qflags |= XFS_UQUOTA_ENFD; | ||
1647 | } | ||
1648 | |||
1649 | if (ap->flags & XFSMNT_GQUOTA) { | ||
1650 | mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE); | ||
1651 | if (ap->flags & XFSMNT_GQUOTAENF) | ||
1652 | mp->m_qflags |= XFS_OQUOTA_ENFD; | ||
1653 | } else if (ap->flags & XFSMNT_PQUOTA) { | ||
1654 | mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE); | ||
1655 | if (ap->flags & XFSMNT_PQUOTAENF) | ||
1656 | mp->m_qflags |= XFS_OQUOTA_ENFD; | ||
1657 | } | ||
1658 | |||
1659 | return 0; | 1388 | return 0; |
1660 | } | 1389 | } |
1661 | 1390 | ||
@@ -1667,19 +1396,14 @@ xfs_fs_fill_super( | |||
1667 | { | 1396 | { |
1668 | struct inode *root; | 1397 | struct inode *root; |
1669 | struct xfs_mount *mp = NULL; | 1398 | struct xfs_mount *mp = NULL; |
1670 | struct xfs_mount_args *args; | ||
1671 | int flags = 0, error = ENOMEM; | 1399 | int flags = 0, error = ENOMEM; |
1672 | 1400 | char *mtpt = NULL; | |
1673 | args = xfs_args_allocate(sb, silent); | ||
1674 | if (!args) | ||
1675 | return -ENOMEM; | ||
1676 | 1401 | ||
1677 | mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL); | 1402 | mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL); |
1678 | if (!mp) | 1403 | if (!mp) |
1679 | goto out_free_args; | 1404 | goto out; |
1680 | 1405 | ||
1681 | spin_lock_init(&mp->m_sb_lock); | 1406 | spin_lock_init(&mp->m_sb_lock); |
1682 | mutex_init(&mp->m_ilock); | ||
1683 | mutex_init(&mp->m_growlock); | 1407 | mutex_init(&mp->m_growlock); |
1684 | atomic_set(&mp->m_active_trans, 0); | 1408 | atomic_set(&mp->m_active_trans, 0); |
1685 | INIT_LIST_HEAD(&mp->m_sync_list); | 1409 | INIT_LIST_HEAD(&mp->m_sync_list); |
@@ -1689,12 +1413,9 @@ xfs_fs_fill_super( | |||
1689 | mp->m_super = sb; | 1413 | mp->m_super = sb; |
1690 | sb->s_fs_info = mp; | 1414 | sb->s_fs_info = mp; |
1691 | 1415 | ||
1692 | if (sb->s_flags & MS_RDONLY) | 1416 | error = xfs_parseargs(mp, (char *)data, &mtpt); |
1693 | mp->m_flags |= XFS_MOUNT_RDONLY; | ||
1694 | |||
1695 | error = xfs_parseargs(mp, (char *)data, args, 0); | ||
1696 | if (error) | 1417 | if (error) |
1697 | goto out_free_mp; | 1418 | goto out_free_fsname; |
1698 | 1419 | ||
1699 | sb_min_blocksize(sb, BBSIZE); | 1420 | sb_min_blocksize(sb, BBSIZE); |
1700 | sb->s_xattr = xfs_xattr_handlers; | 1421 | sb->s_xattr = xfs_xattr_handlers; |
@@ -1702,33 +1423,28 @@ xfs_fs_fill_super( | |||
1702 | sb->s_qcop = &xfs_quotactl_operations; | 1423 | sb->s_qcop = &xfs_quotactl_operations; |
1703 | sb->s_op = &xfs_super_operations; | 1424 | sb->s_op = &xfs_super_operations; |
1704 | 1425 | ||
1705 | error = xfs_dmops_get(mp, args); | 1426 | error = xfs_dmops_get(mp); |
1706 | if (error) | 1427 | if (error) |
1707 | goto out_free_mp; | 1428 | goto out_free_fsname; |
1708 | error = xfs_qmops_get(mp, args); | 1429 | error = xfs_qmops_get(mp); |
1709 | if (error) | 1430 | if (error) |
1710 | goto out_put_dmops; | 1431 | goto out_put_dmops; |
1711 | 1432 | ||
1712 | if (args->flags & XFSMNT_QUIET) | 1433 | if (silent) |
1713 | flags |= XFS_MFSI_QUIET; | 1434 | flags |= XFS_MFSI_QUIET; |
1714 | 1435 | ||
1715 | error = xfs_open_devices(mp, args); | 1436 | error = xfs_open_devices(mp); |
1716 | if (error) | 1437 | if (error) |
1717 | goto out_put_qmops; | 1438 | goto out_put_qmops; |
1718 | 1439 | ||
1719 | if (xfs_icsb_init_counters(mp)) | 1440 | if (xfs_icsb_init_counters(mp)) |
1720 | mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB; | 1441 | mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB; |
1721 | 1442 | ||
1722 | /* | ||
1723 | * Setup flags based on mount(2) options and then the superblock | ||
1724 | */ | ||
1725 | error = xfs_start_flags(args, mp); | ||
1726 | if (error) | ||
1727 | goto out_free_fsname; | ||
1728 | error = xfs_readsb(mp, flags); | 1443 | error = xfs_readsb(mp, flags); |
1729 | if (error) | 1444 | if (error) |
1730 | goto out_free_fsname; | 1445 | goto out_destroy_counters; |
1731 | error = xfs_finish_flags(args, mp); | 1446 | |
1447 | error = xfs_finish_flags(mp); | ||
1732 | if (error) | 1448 | if (error) |
1733 | goto out_free_sb; | 1449 | goto out_free_sb; |
1734 | 1450 | ||
@@ -1747,7 +1463,7 @@ xfs_fs_fill_super( | |||
1747 | if (error) | 1463 | if (error) |
1748 | goto out_filestream_unmount; | 1464 | goto out_filestream_unmount; |
1749 | 1465 | ||
1750 | XFS_SEND_MOUNT(mp, DM_RIGHT_NULL, args->mtpt, args->fsname); | 1466 | XFS_SEND_MOUNT(mp, DM_RIGHT_NULL, mtpt, mp->m_fsname); |
1751 | 1467 | ||
1752 | sb->s_dirt = 1; | 1468 | sb->s_dirt = 1; |
1753 | sb->s_magic = XFS_SB_MAGIC; | 1469 | sb->s_magic = XFS_SB_MAGIC; |
@@ -1772,35 +1488,31 @@ xfs_fs_fill_super( | |||
1772 | goto fail_vnrele; | 1488 | goto fail_vnrele; |
1773 | } | 1489 | } |
1774 | 1490 | ||
1775 | mp->m_sync_work.w_syncer = xfs_sync_worker; | 1491 | error = xfs_syncd_init(mp); |
1776 | mp->m_sync_work.w_mount = mp; | 1492 | if (error) |
1777 | mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd"); | ||
1778 | if (IS_ERR(mp->m_sync_task)) { | ||
1779 | error = -PTR_ERR(mp->m_sync_task); | ||
1780 | goto fail_vnrele; | 1493 | goto fail_vnrele; |
1781 | } | ||
1782 | 1494 | ||
1783 | xfs_itrace_exit(XFS_I(sb->s_root->d_inode)); | 1495 | kfree(mtpt); |
1784 | 1496 | ||
1785 | kfree(args); | 1497 | xfs_itrace_exit(XFS_I(sb->s_root->d_inode)); |
1786 | return 0; | 1498 | return 0; |
1787 | 1499 | ||
1788 | out_filestream_unmount: | 1500 | out_filestream_unmount: |
1789 | xfs_filestream_unmount(mp); | 1501 | xfs_filestream_unmount(mp); |
1790 | out_free_sb: | 1502 | out_free_sb: |
1791 | xfs_freesb(mp); | 1503 | xfs_freesb(mp); |
1792 | out_free_fsname: | 1504 | out_destroy_counters: |
1793 | xfs_free_fsname(mp); | ||
1794 | xfs_icsb_destroy_counters(mp); | 1505 | xfs_icsb_destroy_counters(mp); |
1795 | xfs_close_devices(mp); | 1506 | xfs_close_devices(mp); |
1796 | out_put_qmops: | 1507 | out_put_qmops: |
1797 | xfs_qmops_put(mp); | 1508 | xfs_qmops_put(mp); |
1798 | out_put_dmops: | 1509 | out_put_dmops: |
1799 | xfs_dmops_put(mp); | 1510 | xfs_dmops_put(mp); |
1800 | out_free_mp: | 1511 | out_free_fsname: |
1512 | xfs_free_fsname(mp); | ||
1513 | kfree(mtpt); | ||
1801 | kfree(mp); | 1514 | kfree(mp); |
1802 | out_free_args: | 1515 | out: |
1803 | kfree(args); | ||
1804 | return -error; | 1516 | return -error; |
1805 | 1517 | ||
1806 | fail_vnrele: | 1518 | fail_vnrele: |
@@ -1820,8 +1532,6 @@ xfs_fs_fill_super( | |||
1820 | xfs_filestream_unmount(mp); | 1532 | xfs_filestream_unmount(mp); |
1821 | 1533 | ||
1822 | XFS_bflush(mp->m_ddev_targp); | 1534 | XFS_bflush(mp->m_ddev_targp); |
1823 | error = xfs_unmount_flush(mp, 0); | ||
1824 | WARN_ON(error); | ||
1825 | 1535 | ||
1826 | xfs_unmountfs(mp); | 1536 | xfs_unmountfs(mp); |
1827 | goto out_free_sb; | 1537 | goto out_free_sb; |
@@ -1882,10 +1592,19 @@ xfs_alloc_trace_bufs(void) | |||
1882 | if (!xfs_bmap_trace_buf) | 1592 | if (!xfs_bmap_trace_buf) |
1883 | goto out_free_alloc_trace; | 1593 | goto out_free_alloc_trace; |
1884 | #endif | 1594 | #endif |
1885 | #ifdef XFS_BMBT_TRACE | 1595 | #ifdef XFS_BTREE_TRACE |
1596 | xfs_allocbt_trace_buf = ktrace_alloc(XFS_ALLOCBT_TRACE_SIZE, | ||
1597 | KM_MAYFAIL); | ||
1598 | if (!xfs_allocbt_trace_buf) | ||
1599 | goto out_free_bmap_trace; | ||
1600 | |||
1601 | xfs_inobt_trace_buf = ktrace_alloc(XFS_INOBT_TRACE_SIZE, KM_MAYFAIL); | ||
1602 | if (!xfs_inobt_trace_buf) | ||
1603 | goto out_free_allocbt_trace; | ||
1604 | |||
1886 | xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_MAYFAIL); | 1605 | xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_MAYFAIL); |
1887 | if (!xfs_bmbt_trace_buf) | 1606 | if (!xfs_bmbt_trace_buf) |
1888 | goto out_free_bmap_trace; | 1607 | goto out_free_inobt_trace; |
1889 | #endif | 1608 | #endif |
1890 | #ifdef XFS_ATTR_TRACE | 1609 | #ifdef XFS_ATTR_TRACE |
1891 | xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_MAYFAIL); | 1610 | xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_MAYFAIL); |
@@ -1907,8 +1626,12 @@ xfs_alloc_trace_bufs(void) | |||
1907 | ktrace_free(xfs_attr_trace_buf); | 1626 | ktrace_free(xfs_attr_trace_buf); |
1908 | out_free_bmbt_trace: | 1627 | out_free_bmbt_trace: |
1909 | #endif | 1628 | #endif |
1910 | #ifdef XFS_BMBT_TRACE | 1629 | #ifdef XFS_BTREE_TRACE |
1911 | ktrace_free(xfs_bmbt_trace_buf); | 1630 | ktrace_free(xfs_bmbt_trace_buf); |
1631 | out_free_inobt_trace: | ||
1632 | ktrace_free(xfs_inobt_trace_buf); | ||
1633 | out_free_allocbt_trace: | ||
1634 | ktrace_free(xfs_allocbt_trace_buf); | ||
1912 | out_free_bmap_trace: | 1635 | out_free_bmap_trace: |
1913 | #endif | 1636 | #endif |
1914 | #ifdef XFS_BMAP_TRACE | 1637 | #ifdef XFS_BMAP_TRACE |
@@ -1931,8 +1654,10 @@ xfs_free_trace_bufs(void) | |||
1931 | #ifdef XFS_ATTR_TRACE | 1654 | #ifdef XFS_ATTR_TRACE |
1932 | ktrace_free(xfs_attr_trace_buf); | 1655 | ktrace_free(xfs_attr_trace_buf); |
1933 | #endif | 1656 | #endif |
1934 | #ifdef XFS_BMBT_TRACE | 1657 | #ifdef XFS_BTREE_TRACE |
1935 | ktrace_free(xfs_bmbt_trace_buf); | 1658 | ktrace_free(xfs_bmbt_trace_buf); |
1659 | ktrace_free(xfs_inobt_trace_buf); | ||
1660 | ktrace_free(xfs_allocbt_trace_buf); | ||
1936 | #endif | 1661 | #endif |
1937 | #ifdef XFS_BMAP_TRACE | 1662 | #ifdef XFS_BMAP_TRACE |
1938 | ktrace_free(xfs_bmap_trace_buf); | 1663 | ktrace_free(xfs_bmap_trace_buf); |
@@ -1945,16 +1670,10 @@ xfs_free_trace_bufs(void) | |||
1945 | STATIC int __init | 1670 | STATIC int __init |
1946 | xfs_init_zones(void) | 1671 | xfs_init_zones(void) |
1947 | { | 1672 | { |
1948 | xfs_vnode_zone = kmem_zone_init_flags(sizeof(struct inode), "xfs_vnode", | ||
1949 | KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | | ||
1950 | KM_ZONE_SPREAD, | ||
1951 | xfs_fs_inode_init_once); | ||
1952 | if (!xfs_vnode_zone) | ||
1953 | goto out; | ||
1954 | 1673 | ||
1955 | xfs_ioend_zone = kmem_zone_init(sizeof(xfs_ioend_t), "xfs_ioend"); | 1674 | xfs_ioend_zone = kmem_zone_init(sizeof(xfs_ioend_t), "xfs_ioend"); |
1956 | if (!xfs_ioend_zone) | 1675 | if (!xfs_ioend_zone) |
1957 | goto out_destroy_vnode_zone; | 1676 | goto out; |
1958 | 1677 | ||
1959 | xfs_ioend_pool = mempool_create_slab_pool(4 * MAX_BUF_PER_PAGE, | 1678 | xfs_ioend_pool = mempool_create_slab_pool(4 * MAX_BUF_PER_PAGE, |
1960 | xfs_ioend_zone); | 1679 | xfs_ioend_zone); |
@@ -1970,6 +1689,7 @@ xfs_init_zones(void) | |||
1970 | "xfs_bmap_free_item"); | 1689 | "xfs_bmap_free_item"); |
1971 | if (!xfs_bmap_free_item_zone) | 1690 | if (!xfs_bmap_free_item_zone) |
1972 | goto out_destroy_log_ticket_zone; | 1691 | goto out_destroy_log_ticket_zone; |
1692 | |||
1973 | xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t), | 1693 | xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t), |
1974 | "xfs_btree_cur"); | 1694 | "xfs_btree_cur"); |
1975 | if (!xfs_btree_cur_zone) | 1695 | if (!xfs_btree_cur_zone) |
@@ -2017,8 +1737,8 @@ xfs_init_zones(void) | |||
2017 | 1737 | ||
2018 | xfs_inode_zone = | 1738 | xfs_inode_zone = |
2019 | kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode", | 1739 | kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode", |
2020 | KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | | 1740 | KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | KM_ZONE_SPREAD, |
2021 | KM_ZONE_SPREAD, NULL); | 1741 | xfs_fs_inode_init_once); |
2022 | if (!xfs_inode_zone) | 1742 | if (!xfs_inode_zone) |
2023 | goto out_destroy_efi_zone; | 1743 | goto out_destroy_efi_zone; |
2024 | 1744 | ||
@@ -2066,8 +1786,6 @@ xfs_init_zones(void) | |||
2066 | mempool_destroy(xfs_ioend_pool); | 1786 | mempool_destroy(xfs_ioend_pool); |
2067 | out_destroy_ioend_zone: | 1787 | out_destroy_ioend_zone: |
2068 | kmem_zone_destroy(xfs_ioend_zone); | 1788 | kmem_zone_destroy(xfs_ioend_zone); |
2069 | out_destroy_vnode_zone: | ||
2070 | kmem_zone_destroy(xfs_vnode_zone); | ||
2071 | out: | 1789 | out: |
2072 | return -ENOMEM; | 1790 | return -ENOMEM; |
2073 | } | 1791 | } |
@@ -2092,7 +1810,6 @@ xfs_destroy_zones(void) | |||
2092 | kmem_zone_destroy(xfs_log_ticket_zone); | 1810 | kmem_zone_destroy(xfs_log_ticket_zone); |
2093 | mempool_destroy(xfs_ioend_pool); | 1811 | mempool_destroy(xfs_ioend_pool); |
2094 | kmem_zone_destroy(xfs_ioend_zone); | 1812 | kmem_zone_destroy(xfs_ioend_zone); |
2095 | kmem_zone_destroy(xfs_vnode_zone); | ||
2096 | 1813 | ||
2097 | } | 1814 | } |
2098 | 1815 | ||
@@ -2100,13 +1817,12 @@ STATIC int __init | |||
2100 | init_xfs_fs(void) | 1817 | init_xfs_fs(void) |
2101 | { | 1818 | { |
2102 | int error; | 1819 | int error; |
2103 | static char message[] __initdata = KERN_INFO \ | ||
2104 | XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled\n"; | ||
2105 | 1820 | ||
2106 | printk(message); | 1821 | printk(KERN_INFO XFS_VERSION_STRING " with " |
1822 | XFS_BUILD_OPTIONS " enabled\n"); | ||
2107 | 1823 | ||
2108 | ktrace_init(64); | 1824 | ktrace_init(64); |
2109 | vn_init(); | 1825 | xfs_ioend_init(); |
2110 | xfs_dir_startup(); | 1826 | xfs_dir_startup(); |
2111 | 1827 | ||
2112 | error = xfs_init_zones(); | 1828 | error = xfs_init_zones(); |
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index fe2ef4e6a0f9..d5d776d4cd67 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h | |||
@@ -20,24 +20,12 @@ | |||
20 | 20 | ||
21 | #include <linux/exportfs.h> | 21 | #include <linux/exportfs.h> |
22 | 22 | ||
23 | #ifdef CONFIG_XFS_DMAPI | ||
24 | # define vfs_insertdmapi(vfs) vfs_insertops(vfsp, &xfs_dmops) | ||
25 | # define vfs_initdmapi() dmapi_init() | ||
26 | # define vfs_exitdmapi() dmapi_uninit() | ||
27 | #else | ||
28 | # define vfs_insertdmapi(vfs) do { } while (0) | ||
29 | # define vfs_initdmapi() do { } while (0) | ||
30 | # define vfs_exitdmapi() do { } while (0) | ||
31 | #endif | ||
32 | |||
33 | #ifdef CONFIG_XFS_QUOTA | 23 | #ifdef CONFIG_XFS_QUOTA |
34 | # define vfs_insertquota(vfs) vfs_insertops(vfsp, &xfs_qmops) | ||
35 | extern void xfs_qm_init(void); | 24 | extern void xfs_qm_init(void); |
36 | extern void xfs_qm_exit(void); | 25 | extern void xfs_qm_exit(void); |
37 | # define vfs_initquota() xfs_qm_init() | 26 | # define vfs_initquota() xfs_qm_init() |
38 | # define vfs_exitquota() xfs_qm_exit() | 27 | # define vfs_exitquota() xfs_qm_exit() |
39 | #else | 28 | #else |
40 | # define vfs_insertquota(vfs) do { } while (0) | ||
41 | # define vfs_initquota() do { } while (0) | 29 | # define vfs_initquota() do { } while (0) |
42 | # define vfs_exitquota() do { } while (0) | 30 | # define vfs_exitquota() do { } while (0) |
43 | #endif | 31 | #endif |
@@ -101,9 +89,6 @@ struct block_device; | |||
101 | 89 | ||
102 | extern __uint64_t xfs_max_file_offset(unsigned int); | 90 | extern __uint64_t xfs_max_file_offset(unsigned int); |
103 | 91 | ||
104 | extern void xfs_flush_inode(struct xfs_inode *); | ||
105 | extern void xfs_flush_device(struct xfs_inode *); | ||
106 | |||
107 | extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); | 92 | extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); |
108 | 93 | ||
109 | extern const struct export_operations xfs_export_operations; | 94 | extern const struct export_operations xfs_export_operations; |
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c new file mode 100644 index 000000000000..2ed035354c26 --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
@@ -0,0 +1,762 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #include "xfs.h" | ||
19 | #include "xfs_fs.h" | ||
20 | #include "xfs_types.h" | ||
21 | #include "xfs_bit.h" | ||
22 | #include "xfs_log.h" | ||
23 | #include "xfs_inum.h" | ||
24 | #include "xfs_trans.h" | ||
25 | #include "xfs_sb.h" | ||
26 | #include "xfs_ag.h" | ||
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | ||
30 | #include "xfs_bmap_btree.h" | ||
31 | #include "xfs_alloc_btree.h" | ||
32 | #include "xfs_ialloc_btree.h" | ||
33 | #include "xfs_btree.h" | ||
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_inode.h" | ||
37 | #include "xfs_dinode.h" | ||
38 | #include "xfs_error.h" | ||
39 | #include "xfs_mru_cache.h" | ||
40 | #include "xfs_filestream.h" | ||
41 | #include "xfs_vnodeops.h" | ||
42 | #include "xfs_utils.h" | ||
43 | #include "xfs_buf_item.h" | ||
44 | #include "xfs_inode_item.h" | ||
45 | #include "xfs_rw.h" | ||
46 | |||
47 | #include <linux/kthread.h> | ||
48 | #include <linux/freezer.h> | ||
49 | |||
50 | /* | ||
51 | * Sync all the inodes in the given AG according to the | ||
52 | * direction given by the flags. | ||
53 | */ | ||
54 | STATIC int | ||
55 | xfs_sync_inodes_ag( | ||
56 | xfs_mount_t *mp, | ||
57 | int ag, | ||
58 | int flags) | ||
59 | { | ||
60 | xfs_perag_t *pag = &mp->m_perag[ag]; | ||
61 | int nr_found; | ||
62 | uint32_t first_index = 0; | ||
63 | int error = 0; | ||
64 | int last_error = 0; | ||
65 | int fflag = XFS_B_ASYNC; | ||
66 | |||
67 | if (flags & SYNC_DELWRI) | ||
68 | fflag = XFS_B_DELWRI; | ||
69 | if (flags & SYNC_WAIT) | ||
70 | fflag = 0; /* synchronous overrides all */ | ||
71 | |||
72 | do { | ||
73 | struct inode *inode; | ||
74 | xfs_inode_t *ip = NULL; | ||
75 | int lock_flags = XFS_ILOCK_SHARED; | ||
76 | |||
77 | /* | ||
78 | * use a gang lookup to find the next inode in the tree | ||
79 | * as the tree is sparse and a gang lookup walks to find | ||
80 | * the number of objects requested. | ||
81 | */ | ||
82 | read_lock(&pag->pag_ici_lock); | ||
83 | nr_found = radix_tree_gang_lookup(&pag->pag_ici_root, | ||
84 | (void**)&ip, first_index, 1); | ||
85 | |||
86 | if (!nr_found) { | ||
87 | read_unlock(&pag->pag_ici_lock); | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * Update the index for the next lookup. Catch overflows | ||
93 | * into the next AG range which can occur if we have inodes | ||
94 | * in the last block of the AG and we are currently | ||
95 | * pointing to the last inode. | ||
96 | */ | ||
97 | first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1); | ||
98 | if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino)) { | ||
99 | read_unlock(&pag->pag_ici_lock); | ||
100 | break; | ||
101 | } | ||
102 | |||
103 | /* nothing to sync during shutdown */ | ||
104 | if (XFS_FORCED_SHUTDOWN(mp)) { | ||
105 | read_unlock(&pag->pag_ici_lock); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * If we can't get a reference on the inode, it must be | ||
111 | * in reclaim. Leave it for the reclaim code to flush. | ||
112 | */ | ||
113 | inode = VFS_I(ip); | ||
114 | if (!igrab(inode)) { | ||
115 | read_unlock(&pag->pag_ici_lock); | ||
116 | continue; | ||
117 | } | ||
118 | read_unlock(&pag->pag_ici_lock); | ||
119 | |||
120 | /* avoid new or bad inodes */ | ||
121 | if (is_bad_inode(inode) || | ||
122 | xfs_iflags_test(ip, XFS_INEW)) { | ||
123 | IRELE(ip); | ||
124 | continue; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * If we have to flush data or wait for I/O completion | ||
129 | * we need to hold the iolock. | ||
130 | */ | ||
131 | if ((flags & SYNC_DELWRI) && VN_DIRTY(inode)) { | ||
132 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | ||
133 | lock_flags |= XFS_IOLOCK_SHARED; | ||
134 | error = xfs_flush_pages(ip, 0, -1, fflag, FI_NONE); | ||
135 | if (flags & SYNC_IOWAIT) | ||
136 | xfs_ioend_wait(ip); | ||
137 | } | ||
138 | xfs_ilock(ip, XFS_ILOCK_SHARED); | ||
139 | |||
140 | if ((flags & SYNC_ATTR) && !xfs_inode_clean(ip)) { | ||
141 | if (flags & SYNC_WAIT) { | ||
142 | xfs_iflock(ip); | ||
143 | if (!xfs_inode_clean(ip)) | ||
144 | error = xfs_iflush(ip, XFS_IFLUSH_SYNC); | ||
145 | else | ||
146 | xfs_ifunlock(ip); | ||
147 | } else if (xfs_iflock_nowait(ip)) { | ||
148 | if (!xfs_inode_clean(ip)) | ||
149 | error = xfs_iflush(ip, XFS_IFLUSH_DELWRI); | ||
150 | else | ||
151 | xfs_ifunlock(ip); | ||
152 | } | ||
153 | } | ||
154 | xfs_iput(ip, lock_flags); | ||
155 | |||
156 | if (error) | ||
157 | last_error = error; | ||
158 | /* | ||
159 | * bail out if the filesystem is corrupted. | ||
160 | */ | ||
161 | if (error == EFSCORRUPTED) | ||
162 | return XFS_ERROR(error); | ||
163 | |||
164 | } while (nr_found); | ||
165 | |||
166 | return last_error; | ||
167 | } | ||
168 | |||
169 | int | ||
170 | xfs_sync_inodes( | ||
171 | xfs_mount_t *mp, | ||
172 | int flags) | ||
173 | { | ||
174 | int error; | ||
175 | int last_error; | ||
176 | int i; | ||
177 | int lflags = XFS_LOG_FORCE; | ||
178 | |||
179 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
180 | return 0; | ||
181 | error = 0; | ||
182 | last_error = 0; | ||
183 | |||
184 | if (flags & SYNC_WAIT) | ||
185 | lflags |= XFS_LOG_SYNC; | ||
186 | |||
187 | for (i = 0; i < mp->m_sb.sb_agcount; i++) { | ||
188 | if (!mp->m_perag[i].pag_ici_init) | ||
189 | continue; | ||
190 | error = xfs_sync_inodes_ag(mp, i, flags); | ||
191 | if (error) | ||
192 | last_error = error; | ||
193 | if (error == EFSCORRUPTED) | ||
194 | break; | ||
195 | } | ||
196 | if (flags & SYNC_DELWRI) | ||
197 | xfs_log_force(mp, 0, lflags); | ||
198 | |||
199 | return XFS_ERROR(last_error); | ||
200 | } | ||
201 | |||
202 | STATIC int | ||
203 | xfs_commit_dummy_trans( | ||
204 | struct xfs_mount *mp, | ||
205 | uint log_flags) | ||
206 | { | ||
207 | struct xfs_inode *ip = mp->m_rootip; | ||
208 | struct xfs_trans *tp; | ||
209 | int error; | ||
210 | |||
211 | /* | ||
212 | * Put a dummy transaction in the log to tell recovery | ||
213 | * that all others are OK. | ||
214 | */ | ||
215 | tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); | ||
216 | error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0); | ||
217 | if (error) { | ||
218 | xfs_trans_cancel(tp, 0); | ||
219 | return error; | ||
220 | } | ||
221 | |||
222 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
223 | |||
224 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
225 | xfs_trans_ihold(tp, ip); | ||
226 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
227 | /* XXX(hch): ignoring the error here.. */ | ||
228 | error = xfs_trans_commit(tp, 0); | ||
229 | |||
230 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
231 | |||
232 | xfs_log_force(mp, 0, log_flags); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | int | ||
237 | xfs_sync_fsdata( | ||
238 | struct xfs_mount *mp, | ||
239 | int flags) | ||
240 | { | ||
241 | struct xfs_buf *bp; | ||
242 | struct xfs_buf_log_item *bip; | ||
243 | int error = 0; | ||
244 | |||
245 | /* | ||
246 | * If this is xfssyncd() then only sync the superblock if we can | ||
247 | * lock it without sleeping and it is not pinned. | ||
248 | */ | ||
249 | if (flags & SYNC_BDFLUSH) { | ||
250 | ASSERT(!(flags & SYNC_WAIT)); | ||
251 | |||
252 | bp = xfs_getsb(mp, XFS_BUF_TRYLOCK); | ||
253 | if (!bp) | ||
254 | goto out; | ||
255 | |||
256 | bip = XFS_BUF_FSPRIVATE(bp, struct xfs_buf_log_item *); | ||
257 | if (!bip || !xfs_buf_item_dirty(bip) || XFS_BUF_ISPINNED(bp)) | ||
258 | goto out_brelse; | ||
259 | } else { | ||
260 | bp = xfs_getsb(mp, 0); | ||
261 | |||
262 | /* | ||
263 | * If the buffer is pinned then push on the log so we won't | ||
264 | * get stuck waiting in the write for someone, maybe | ||
265 | * ourselves, to flush the log. | ||
266 | * | ||
267 | * Even though we just pushed the log above, we did not have | ||
268 | * the superblock buffer locked at that point so it can | ||
269 | * become pinned in between there and here. | ||
270 | */ | ||
271 | if (XFS_BUF_ISPINNED(bp)) | ||
272 | xfs_log_force(mp, 0, XFS_LOG_FORCE); | ||
273 | } | ||
274 | |||
275 | |||
276 | if (flags & SYNC_WAIT) | ||
277 | XFS_BUF_UNASYNC(bp); | ||
278 | else | ||
279 | XFS_BUF_ASYNC(bp); | ||
280 | |||
281 | return xfs_bwrite(mp, bp); | ||
282 | |||
283 | out_brelse: | ||
284 | xfs_buf_relse(bp); | ||
285 | out: | ||
286 | return error; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * When remounting a filesystem read-only or freezing the filesystem, we have | ||
291 | * two phases to execute. This first phase is syncing the data before we | ||
292 | * quiesce the filesystem, and the second is flushing all the inodes out after | ||
293 | * we've waited for all the transactions created by the first phase to | ||
294 | * complete. The second phase ensures that the inodes are written to their | ||
295 | * location on disk rather than just existing in transactions in the log. This | ||
296 | * means after a quiesce there is no log replay required to write the inodes to | ||
297 | * disk (this is the main difference between a sync and a quiesce). | ||
298 | */ | ||
299 | /* | ||
300 | * First stage of freeze - no writers will make progress now we are here, | ||
301 | * so we flush delwri and delalloc buffers here, then wait for all I/O to | ||
302 | * complete. Data is frozen at that point. Metadata is not frozen, | ||
303 | * transactions can still occur here so don't bother flushing the buftarg | ||
304 | * because it'll just get dirty again. | ||
305 | */ | ||
306 | int | ||
307 | xfs_quiesce_data( | ||
308 | struct xfs_mount *mp) | ||
309 | { | ||
310 | int error; | ||
311 | |||
312 | /* push non-blocking */ | ||
313 | xfs_sync_inodes(mp, SYNC_DELWRI|SYNC_BDFLUSH); | ||
314 | XFS_QM_DQSYNC(mp, SYNC_BDFLUSH); | ||
315 | xfs_filestream_flush(mp); | ||
316 | |||
317 | /* push and block */ | ||
318 | xfs_sync_inodes(mp, SYNC_DELWRI|SYNC_WAIT|SYNC_IOWAIT); | ||
319 | XFS_QM_DQSYNC(mp, SYNC_WAIT); | ||
320 | |||
321 | /* write superblock and hoover up shutdown errors */ | ||
322 | error = xfs_sync_fsdata(mp, 0); | ||
323 | |||
324 | /* flush data-only devices */ | ||
325 | if (mp->m_rtdev_targp) | ||
326 | XFS_bflush(mp->m_rtdev_targp); | ||
327 | |||
328 | return error; | ||
329 | } | ||
330 | |||
331 | STATIC void | ||
332 | xfs_quiesce_fs( | ||
333 | struct xfs_mount *mp) | ||
334 | { | ||
335 | int count = 0, pincount; | ||
336 | |||
337 | xfs_flush_buftarg(mp->m_ddev_targp, 0); | ||
338 | xfs_reclaim_inodes(mp, 0, XFS_IFLUSH_DELWRI_ELSE_ASYNC); | ||
339 | |||
340 | /* | ||
341 | * This loop must run at least twice. The first instance of the loop | ||
342 | * will flush most meta data but that will generate more meta data | ||
343 | * (typically directory updates). Which then must be flushed and | ||
344 | * logged before we can write the unmount record. | ||
345 | */ | ||
346 | do { | ||
347 | xfs_sync_inodes(mp, SYNC_ATTR|SYNC_WAIT); | ||
348 | pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1); | ||
349 | if (!pincount) { | ||
350 | delay(50); | ||
351 | count++; | ||
352 | } | ||
353 | } while (count < 2); | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * Second stage of a quiesce. The data is already synced, now we have to take | ||
358 | * care of the metadata. New transactions are already blocked, so we need to | ||
359 | * wait for any remaining transactions to drain out before proceding. | ||
360 | */ | ||
361 | void | ||
362 | xfs_quiesce_attr( | ||
363 | struct xfs_mount *mp) | ||
364 | { | ||
365 | int error = 0; | ||
366 | |||
367 | /* wait for all modifications to complete */ | ||
368 | while (atomic_read(&mp->m_active_trans) > 0) | ||
369 | delay(100); | ||
370 | |||
371 | /* flush inodes and push all remaining buffers out to disk */ | ||
372 | xfs_quiesce_fs(mp); | ||
373 | |||
374 | ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0); | ||
375 | |||
376 | /* Push the superblock and write an unmount record */ | ||
377 | error = xfs_log_sbcount(mp, 1); | ||
378 | if (error) | ||
379 | xfs_fs_cmn_err(CE_WARN, mp, | ||
380 | "xfs_attr_quiesce: failed to log sb changes. " | ||
381 | "Frozen image may not be consistent."); | ||
382 | xfs_log_unmount_write(mp); | ||
383 | xfs_unmountfs_writesb(mp); | ||
384 | } | ||
385 | |||
386 | /* | ||
387 | * Enqueue a work item to be picked up by the vfs xfssyncd thread. | ||
388 | * Doing this has two advantages: | ||
389 | * - It saves on stack space, which is tight in certain situations | ||
390 | * - It can be used (with care) as a mechanism to avoid deadlocks. | ||
391 | * Flushing while allocating in a full filesystem requires both. | ||
392 | */ | ||
393 | STATIC void | ||
394 | xfs_syncd_queue_work( | ||
395 | struct xfs_mount *mp, | ||
396 | void *data, | ||
397 | void (*syncer)(struct xfs_mount *, void *)) | ||
398 | { | ||
399 | struct bhv_vfs_sync_work *work; | ||
400 | |||
401 | work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP); | ||
402 | INIT_LIST_HEAD(&work->w_list); | ||
403 | work->w_syncer = syncer; | ||
404 | work->w_data = data; | ||
405 | work->w_mount = mp; | ||
406 | spin_lock(&mp->m_sync_lock); | ||
407 | list_add_tail(&work->w_list, &mp->m_sync_list); | ||
408 | spin_unlock(&mp->m_sync_lock); | ||
409 | wake_up_process(mp->m_sync_task); | ||
410 | } | ||
411 | |||
412 | /* | ||
413 | * Flush delayed allocate data, attempting to free up reserved space | ||
414 | * from existing allocations. At this point a new allocation attempt | ||
415 | * has failed with ENOSPC and we are in the process of scratching our | ||
416 | * heads, looking about for more room... | ||
417 | */ | ||
418 | STATIC void | ||
419 | xfs_flush_inode_work( | ||
420 | struct xfs_mount *mp, | ||
421 | void *arg) | ||
422 | { | ||
423 | struct inode *inode = arg; | ||
424 | filemap_flush(inode->i_mapping); | ||
425 | iput(inode); | ||
426 | } | ||
427 | |||
428 | void | ||
429 | xfs_flush_inode( | ||
430 | xfs_inode_t *ip) | ||
431 | { | ||
432 | struct inode *inode = VFS_I(ip); | ||
433 | |||
434 | igrab(inode); | ||
435 | xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work); | ||
436 | delay(msecs_to_jiffies(500)); | ||
437 | } | ||
438 | |||
439 | /* | ||
440 | * This is the "bigger hammer" version of xfs_flush_inode_work... | ||
441 | * (IOW, "If at first you don't succeed, use a Bigger Hammer"). | ||
442 | */ | ||
443 | STATIC void | ||
444 | xfs_flush_device_work( | ||
445 | struct xfs_mount *mp, | ||
446 | void *arg) | ||
447 | { | ||
448 | struct inode *inode = arg; | ||
449 | sync_blockdev(mp->m_super->s_bdev); | ||
450 | iput(inode); | ||
451 | } | ||
452 | |||
453 | void | ||
454 | xfs_flush_device( | ||
455 | xfs_inode_t *ip) | ||
456 | { | ||
457 | struct inode *inode = VFS_I(ip); | ||
458 | |||
459 | igrab(inode); | ||
460 | xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work); | ||
461 | delay(msecs_to_jiffies(500)); | ||
462 | xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); | ||
463 | } | ||
464 | |||
465 | /* | ||
466 | * Every sync period we need to unpin all items, reclaim inodes, sync | ||
467 | * quota and write out the superblock. We might need to cover the log | ||
468 | * to indicate it is idle. | ||
469 | */ | ||
470 | STATIC void | ||
471 | xfs_sync_worker( | ||
472 | struct xfs_mount *mp, | ||
473 | void *unused) | ||
474 | { | ||
475 | int error; | ||
476 | |||
477 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { | ||
478 | xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE); | ||
479 | xfs_reclaim_inodes(mp, 0, XFS_IFLUSH_DELWRI_ELSE_ASYNC); | ||
480 | /* dgc: errors ignored here */ | ||
481 | error = XFS_QM_DQSYNC(mp, SYNC_BDFLUSH); | ||
482 | error = xfs_sync_fsdata(mp, SYNC_BDFLUSH); | ||
483 | if (xfs_log_need_covered(mp)) | ||
484 | error = xfs_commit_dummy_trans(mp, XFS_LOG_FORCE); | ||
485 | } | ||
486 | mp->m_sync_seq++; | ||
487 | wake_up(&mp->m_wait_single_sync_task); | ||
488 | } | ||
489 | |||
490 | STATIC int | ||
491 | xfssyncd( | ||
492 | void *arg) | ||
493 | { | ||
494 | struct xfs_mount *mp = arg; | ||
495 | long timeleft; | ||
496 | bhv_vfs_sync_work_t *work, *n; | ||
497 | LIST_HEAD (tmp); | ||
498 | |||
499 | set_freezable(); | ||
500 | timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10); | ||
501 | for (;;) { | ||
502 | timeleft = schedule_timeout_interruptible(timeleft); | ||
503 | /* swsusp */ | ||
504 | try_to_freeze(); | ||
505 | if (kthread_should_stop() && list_empty(&mp->m_sync_list)) | ||
506 | break; | ||
507 | |||
508 | spin_lock(&mp->m_sync_lock); | ||
509 | /* | ||
510 | * We can get woken by laptop mode, to do a sync - | ||
511 | * that's the (only!) case where the list would be | ||
512 | * empty with time remaining. | ||
513 | */ | ||
514 | if (!timeleft || list_empty(&mp->m_sync_list)) { | ||
515 | if (!timeleft) | ||
516 | timeleft = xfs_syncd_centisecs * | ||
517 | msecs_to_jiffies(10); | ||
518 | INIT_LIST_HEAD(&mp->m_sync_work.w_list); | ||
519 | list_add_tail(&mp->m_sync_work.w_list, | ||
520 | &mp->m_sync_list); | ||
521 | } | ||
522 | list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list) | ||
523 | list_move(&work->w_list, &tmp); | ||
524 | spin_unlock(&mp->m_sync_lock); | ||
525 | |||
526 | list_for_each_entry_safe(work, n, &tmp, w_list) { | ||
527 | (*work->w_syncer)(mp, work->w_data); | ||
528 | list_del(&work->w_list); | ||
529 | if (work == &mp->m_sync_work) | ||
530 | continue; | ||
531 | kmem_free(work); | ||
532 | } | ||
533 | } | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | int | ||
539 | xfs_syncd_init( | ||
540 | struct xfs_mount *mp) | ||
541 | { | ||
542 | mp->m_sync_work.w_syncer = xfs_sync_worker; | ||
543 | mp->m_sync_work.w_mount = mp; | ||
544 | mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd"); | ||
545 | if (IS_ERR(mp->m_sync_task)) | ||
546 | return -PTR_ERR(mp->m_sync_task); | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | void | ||
551 | xfs_syncd_stop( | ||
552 | struct xfs_mount *mp) | ||
553 | { | ||
554 | kthread_stop(mp->m_sync_task); | ||
555 | } | ||
556 | |||
557 | int | ||
558 | xfs_reclaim_inode( | ||
559 | xfs_inode_t *ip, | ||
560 | int locked, | ||
561 | int sync_mode) | ||
562 | { | ||
563 | xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino); | ||
564 | |||
565 | /* The hash lock here protects a thread in xfs_iget_core from | ||
566 | * racing with us on linking the inode back with a vnode. | ||
567 | * Once we have the XFS_IRECLAIM flag set it will not touch | ||
568 | * us. | ||
569 | */ | ||
570 | write_lock(&pag->pag_ici_lock); | ||
571 | spin_lock(&ip->i_flags_lock); | ||
572 | if (__xfs_iflags_test(ip, XFS_IRECLAIM) || | ||
573 | !__xfs_iflags_test(ip, XFS_IRECLAIMABLE)) { | ||
574 | spin_unlock(&ip->i_flags_lock); | ||
575 | write_unlock(&pag->pag_ici_lock); | ||
576 | if (locked) { | ||
577 | xfs_ifunlock(ip); | ||
578 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
579 | } | ||
580 | return 1; | ||
581 | } | ||
582 | __xfs_iflags_set(ip, XFS_IRECLAIM); | ||
583 | spin_unlock(&ip->i_flags_lock); | ||
584 | write_unlock(&pag->pag_ici_lock); | ||
585 | xfs_put_perag(ip->i_mount, pag); | ||
586 | |||
587 | /* | ||
588 | * If the inode is still dirty, then flush it out. If the inode | ||
589 | * is not in the AIL, then it will be OK to flush it delwri as | ||
590 | * long as xfs_iflush() does not keep any references to the inode. | ||
591 | * We leave that decision up to xfs_iflush() since it has the | ||
592 | * knowledge of whether it's OK to simply do a delwri flush of | ||
593 | * the inode or whether we need to wait until the inode is | ||
594 | * pulled from the AIL. | ||
595 | * We get the flush lock regardless, though, just to make sure | ||
596 | * we don't free it while it is being flushed. | ||
597 | */ | ||
598 | if (!locked) { | ||
599 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
600 | xfs_iflock(ip); | ||
601 | } | ||
602 | |||
603 | /* | ||
604 | * In the case of a forced shutdown we rely on xfs_iflush() to | ||
605 | * wait for the inode to be unpinned before returning an error. | ||
606 | */ | ||
607 | if (!is_bad_inode(VFS_I(ip)) && xfs_iflush(ip, sync_mode) == 0) { | ||
608 | /* synchronize with xfs_iflush_done */ | ||
609 | xfs_iflock(ip); | ||
610 | xfs_ifunlock(ip); | ||
611 | } | ||
612 | |||
613 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
614 | xfs_ireclaim(ip); | ||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | /* | ||
619 | * We set the inode flag atomically with the radix tree tag. | ||
620 | * Once we get tag lookups on the radix tree, this inode flag | ||
621 | * can go away. | ||
622 | */ | ||
623 | void | ||
624 | xfs_inode_set_reclaim_tag( | ||
625 | xfs_inode_t *ip) | ||
626 | { | ||
627 | xfs_mount_t *mp = ip->i_mount; | ||
628 | xfs_perag_t *pag = xfs_get_perag(mp, ip->i_ino); | ||
629 | |||
630 | read_lock(&pag->pag_ici_lock); | ||
631 | spin_lock(&ip->i_flags_lock); | ||
632 | radix_tree_tag_set(&pag->pag_ici_root, | ||
633 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); | ||
634 | __xfs_iflags_set(ip, XFS_IRECLAIMABLE); | ||
635 | spin_unlock(&ip->i_flags_lock); | ||
636 | read_unlock(&pag->pag_ici_lock); | ||
637 | xfs_put_perag(mp, pag); | ||
638 | } | ||
639 | |||
640 | void | ||
641 | __xfs_inode_clear_reclaim_tag( | ||
642 | xfs_mount_t *mp, | ||
643 | xfs_perag_t *pag, | ||
644 | xfs_inode_t *ip) | ||
645 | { | ||
646 | radix_tree_tag_clear(&pag->pag_ici_root, | ||
647 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); | ||
648 | } | ||
649 | |||
650 | void | ||
651 | xfs_inode_clear_reclaim_tag( | ||
652 | xfs_inode_t *ip) | ||
653 | { | ||
654 | xfs_mount_t *mp = ip->i_mount; | ||
655 | xfs_perag_t *pag = xfs_get_perag(mp, ip->i_ino); | ||
656 | |||
657 | read_lock(&pag->pag_ici_lock); | ||
658 | spin_lock(&ip->i_flags_lock); | ||
659 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); | ||
660 | spin_unlock(&ip->i_flags_lock); | ||
661 | read_unlock(&pag->pag_ici_lock); | ||
662 | xfs_put_perag(mp, pag); | ||
663 | } | ||
664 | |||
665 | |||
666 | STATIC void | ||
667 | xfs_reclaim_inodes_ag( | ||
668 | xfs_mount_t *mp, | ||
669 | int ag, | ||
670 | int noblock, | ||
671 | int mode) | ||
672 | { | ||
673 | xfs_inode_t *ip = NULL; | ||
674 | xfs_perag_t *pag = &mp->m_perag[ag]; | ||
675 | int nr_found; | ||
676 | uint32_t first_index; | ||
677 | int skipped; | ||
678 | |||
679 | restart: | ||
680 | first_index = 0; | ||
681 | skipped = 0; | ||
682 | do { | ||
683 | /* | ||
684 | * use a gang lookup to find the next inode in the tree | ||
685 | * as the tree is sparse and a gang lookup walks to find | ||
686 | * the number of objects requested. | ||
687 | */ | ||
688 | read_lock(&pag->pag_ici_lock); | ||
689 | nr_found = radix_tree_gang_lookup_tag(&pag->pag_ici_root, | ||
690 | (void**)&ip, first_index, 1, | ||
691 | XFS_ICI_RECLAIM_TAG); | ||
692 | |||
693 | if (!nr_found) { | ||
694 | read_unlock(&pag->pag_ici_lock); | ||
695 | break; | ||
696 | } | ||
697 | |||
698 | /* | ||
699 | * Update the index for the next lookup. Catch overflows | ||
700 | * into the next AG range which can occur if we have inodes | ||
701 | * in the last block of the AG and we are currently | ||
702 | * pointing to the last inode. | ||
703 | */ | ||
704 | first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1); | ||
705 | if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino)) { | ||
706 | read_unlock(&pag->pag_ici_lock); | ||
707 | break; | ||
708 | } | ||
709 | |||
710 | /* ignore if already under reclaim */ | ||
711 | if (xfs_iflags_test(ip, XFS_IRECLAIM)) { | ||
712 | read_unlock(&pag->pag_ici_lock); | ||
713 | continue; | ||
714 | } | ||
715 | |||
716 | if (noblock) { | ||
717 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { | ||
718 | read_unlock(&pag->pag_ici_lock); | ||
719 | continue; | ||
720 | } | ||
721 | if (xfs_ipincount(ip) || | ||
722 | !xfs_iflock_nowait(ip)) { | ||
723 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
724 | read_unlock(&pag->pag_ici_lock); | ||
725 | continue; | ||
726 | } | ||
727 | } | ||
728 | read_unlock(&pag->pag_ici_lock); | ||
729 | |||
730 | /* | ||
731 | * hmmm - this is an inode already in reclaim. Do | ||
732 | * we even bother catching it here? | ||
733 | */ | ||
734 | if (xfs_reclaim_inode(ip, noblock, mode)) | ||
735 | skipped++; | ||
736 | } while (nr_found); | ||
737 | |||
738 | if (skipped) { | ||
739 | delay(1); | ||
740 | goto restart; | ||
741 | } | ||
742 | return; | ||
743 | |||
744 | } | ||
745 | |||
746 | int | ||
747 | xfs_reclaim_inodes( | ||
748 | xfs_mount_t *mp, | ||
749 | int noblock, | ||
750 | int mode) | ||
751 | { | ||
752 | int i; | ||
753 | |||
754 | for (i = 0; i < mp->m_sb.sb_agcount; i++) { | ||
755 | if (!mp->m_perag[i].pag_ici_init) | ||
756 | continue; | ||
757 | xfs_reclaim_inodes_ag(mp, i, noblock, mode); | ||
758 | } | ||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | |||
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h new file mode 100644 index 000000000000..5f6de1efe1f6 --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_sync.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef XFS_SYNC_H | ||
19 | #define XFS_SYNC_H 1 | ||
20 | |||
21 | struct xfs_mount; | ||
22 | |||
23 | typedef struct bhv_vfs_sync_work { | ||
24 | struct list_head w_list; | ||
25 | struct xfs_mount *w_mount; | ||
26 | void *w_data; /* syncer routine argument */ | ||
27 | void (*w_syncer)(struct xfs_mount *, void *); | ||
28 | } bhv_vfs_sync_work_t; | ||
29 | |||
30 | #define SYNC_ATTR 0x0001 /* sync attributes */ | ||
31 | #define SYNC_DELWRI 0x0002 /* look at delayed writes */ | ||
32 | #define SYNC_WAIT 0x0004 /* wait for i/o to complete */ | ||
33 | #define SYNC_BDFLUSH 0x0008 /* BDFLUSH is calling -- don't block */ | ||
34 | #define SYNC_IOWAIT 0x0010 /* wait for all I/O to complete */ | ||
35 | |||
36 | int xfs_syncd_init(struct xfs_mount *mp); | ||
37 | void xfs_syncd_stop(struct xfs_mount *mp); | ||
38 | |||
39 | int xfs_sync_inodes(struct xfs_mount *mp, int flags); | ||
40 | int xfs_sync_fsdata(struct xfs_mount *mp, int flags); | ||
41 | |||
42 | int xfs_quiesce_data(struct xfs_mount *mp); | ||
43 | void xfs_quiesce_attr(struct xfs_mount *mp); | ||
44 | |||
45 | void xfs_flush_inode(struct xfs_inode *ip); | ||
46 | void xfs_flush_device(struct xfs_inode *ip); | ||
47 | |||
48 | int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode); | ||
49 | int xfs_reclaim_inodes(struct xfs_mount *mp, int noblock, int mode); | ||
50 | |||
51 | void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); | ||
52 | void xfs_inode_clear_reclaim_tag(struct xfs_inode *ip); | ||
53 | void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag, | ||
54 | struct xfs_inode *ip); | ||
55 | #endif | ||
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c index 7dacb5bbde3f..916c0ffb6083 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c | |||
@@ -56,17 +56,6 @@ xfs_stats_clear_proc_handler( | |||
56 | 56 | ||
57 | static ctl_table xfs_table[] = { | 57 | static ctl_table xfs_table[] = { |
58 | { | 58 | { |
59 | .ctl_name = XFS_RESTRICT_CHOWN, | ||
60 | .procname = "restrict_chown", | ||
61 | .data = &xfs_params.restrict_chown.val, | ||
62 | .maxlen = sizeof(int), | ||
63 | .mode = 0644, | ||
64 | .proc_handler = &proc_dointvec_minmax, | ||
65 | .strategy = &sysctl_intvec, | ||
66 | .extra1 = &xfs_params.restrict_chown.min, | ||
67 | .extra2 = &xfs_params.restrict_chown.max | ||
68 | }, | ||
69 | { | ||
70 | .ctl_name = XFS_SGID_INHERIT, | 59 | .ctl_name = XFS_SGID_INHERIT, |
71 | .procname = "irix_sgid_inherit", | 60 | .procname = "irix_sgid_inherit", |
72 | .data = &xfs_params.sgid_inherit.val, | 61 | .data = &xfs_params.sgid_inherit.val, |
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/linux-2.6/xfs_sysctl.h index 4aadb8056c37..b9937d450f8e 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.h +++ b/fs/xfs/linux-2.6/xfs_sysctl.h | |||
@@ -31,7 +31,6 @@ typedef struct xfs_sysctl_val { | |||
31 | } xfs_sysctl_val_t; | 31 | } xfs_sysctl_val_t; |
32 | 32 | ||
33 | typedef struct xfs_param { | 33 | typedef struct xfs_param { |
34 | xfs_sysctl_val_t restrict_chown;/* Root/non-root can give away files.*/ | ||
35 | xfs_sysctl_val_t sgid_inherit; /* Inherit S_ISGID if process' GID is | 34 | xfs_sysctl_val_t sgid_inherit; /* Inherit S_ISGID if process' GID is |
36 | * not a member of parent dir GID. */ | 35 | * not a member of parent dir GID. */ |
37 | xfs_sysctl_val_t symlink_mode; /* Link creat mode affected by umask */ | 36 | xfs_sysctl_val_t symlink_mode; /* Link creat mode affected by umask */ |
@@ -68,7 +67,7 @@ typedef struct xfs_param { | |||
68 | enum { | 67 | enum { |
69 | /* XFS_REFCACHE_SIZE = 1 */ | 68 | /* XFS_REFCACHE_SIZE = 1 */ |
70 | /* XFS_REFCACHE_PURGE = 2 */ | 69 | /* XFS_REFCACHE_PURGE = 2 */ |
71 | XFS_RESTRICT_CHOWN = 3, | 70 | /* XFS_RESTRICT_CHOWN = 3 */ |
72 | XFS_SGID_INHERIT = 4, | 71 | XFS_SGID_INHERIT = 4, |
73 | XFS_SYMLINK_MODE = 5, | 72 | XFS_SYMLINK_MODE = 5, |
74 | XFS_PANIC_MASK = 6, | 73 | XFS_PANIC_MASK = 6, |
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h deleted file mode 100644 index 7e60c7776b1c..000000000000 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_VFS_H__ | ||
19 | #define __XFS_VFS_H__ | ||
20 | |||
21 | #include <linux/vfs.h> | ||
22 | #include "xfs_fs.h" | ||
23 | |||
24 | struct inode; | ||
25 | |||
26 | struct fid; | ||
27 | struct cred; | ||
28 | struct seq_file; | ||
29 | struct super_block; | ||
30 | struct xfs_inode; | ||
31 | struct xfs_mount; | ||
32 | struct xfs_mount_args; | ||
33 | |||
34 | typedef struct kstatfs bhv_statvfs_t; | ||
35 | |||
36 | typedef struct bhv_vfs_sync_work { | ||
37 | struct list_head w_list; | ||
38 | struct xfs_mount *w_mount; | ||
39 | void *w_data; /* syncer routine argument */ | ||
40 | void (*w_syncer)(struct xfs_mount *, void *); | ||
41 | } bhv_vfs_sync_work_t; | ||
42 | |||
43 | #define SYNC_ATTR 0x0001 /* sync attributes */ | ||
44 | #define SYNC_CLOSE 0x0002 /* close file system down */ | ||
45 | #define SYNC_DELWRI 0x0004 /* look at delayed writes */ | ||
46 | #define SYNC_WAIT 0x0008 /* wait for i/o to complete */ | ||
47 | #define SYNC_BDFLUSH 0x0010 /* BDFLUSH is calling -- don't block */ | ||
48 | #define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ | ||
49 | #define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */ | ||
50 | #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ | ||
51 | #define SYNC_IOWAIT 0x0100 /* wait for all I/O to complete */ | ||
52 | |||
53 | /* | ||
54 | * When remounting a filesystem read-only or freezing the filesystem, | ||
55 | * we have two phases to execute. This first phase is syncing the data | ||
56 | * before we quiesce the fielsystem, and the second is flushing all the | ||
57 | * inodes out after we've waited for all the transactions created by | ||
58 | * the first phase to complete. The second phase uses SYNC_INODE_QUIESCE | ||
59 | * to ensure that the inodes are written to their location on disk | ||
60 | * rather than just existing in transactions in the log. This means | ||
61 | * after a quiesce there is no log replay required to write the inodes | ||
62 | * to disk (this is the main difference between a sync and a quiesce). | ||
63 | */ | ||
64 | #define SYNC_DATA_QUIESCE (SYNC_DELWRI|SYNC_FSDATA|SYNC_WAIT|SYNC_IOWAIT) | ||
65 | #define SYNC_INODE_QUIESCE (SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT) | ||
66 | |||
67 | #define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */ | ||
68 | #define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */ | ||
69 | #define SHUTDOWN_FORCE_UMOUNT 0x0004 /* shutdown from a forced unmount */ | ||
70 | #define SHUTDOWN_CORRUPT_INCORE 0x0008 /* corrupt in-memory data structures */ | ||
71 | #define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */ | ||
72 | #define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */ | ||
73 | |||
74 | #define xfs_test_for_freeze(mp) ((mp)->m_super->s_frozen) | ||
75 | #define xfs_wait_for_freeze(mp,l) vfs_check_frozen((mp)->m_super, (l)) | ||
76 | |||
77 | #endif /* __XFS_VFS_H__ */ | ||
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c deleted file mode 100644 index b52528bbbfff..000000000000 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ /dev/null | |||
@@ -1,145 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #include "xfs.h" | ||
19 | #include "xfs_vnodeops.h" | ||
20 | #include "xfs_bmap_btree.h" | ||
21 | #include "xfs_inode.h" | ||
22 | |||
23 | /* | ||
24 | * And this gunk is needed for xfs_mount.h" | ||
25 | */ | ||
26 | #include "xfs_log.h" | ||
27 | #include "xfs_trans.h" | ||
28 | #include "xfs_sb.h" | ||
29 | #include "xfs_dmapi.h" | ||
30 | #include "xfs_inum.h" | ||
31 | #include "xfs_ag.h" | ||
32 | #include "xfs_mount.h" | ||
33 | |||
34 | |||
35 | /* | ||
36 | * Dedicated vnode inactive/reclaim sync wait queues. | ||
37 | * Prime number of hash buckets since address is used as the key. | ||
38 | */ | ||
39 | #define NVSYNC 37 | ||
40 | #define vptosync(v) (&vsync[((unsigned long)v) % NVSYNC]) | ||
41 | static wait_queue_head_t vsync[NVSYNC]; | ||
42 | |||
43 | void __init | ||
44 | vn_init(void) | ||
45 | { | ||
46 | int i; | ||
47 | |||
48 | for (i = 0; i < NVSYNC; i++) | ||
49 | init_waitqueue_head(&vsync[i]); | ||
50 | } | ||
51 | |||
52 | void | ||
53 | vn_iowait( | ||
54 | xfs_inode_t *ip) | ||
55 | { | ||
56 | wait_queue_head_t *wq = vptosync(ip); | ||
57 | |||
58 | wait_event(*wq, (atomic_read(&ip->i_iocount) == 0)); | ||
59 | } | ||
60 | |||
61 | void | ||
62 | vn_iowake( | ||
63 | xfs_inode_t *ip) | ||
64 | { | ||
65 | if (atomic_dec_and_test(&ip->i_iocount)) | ||
66 | wake_up(vptosync(ip)); | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | * Volume managers supporting multiple paths can send back ENODEV when the | ||
71 | * final path disappears. In this case continuing to fill the page cache | ||
72 | * with dirty data which cannot be written out is evil, so prevent that. | ||
73 | */ | ||
74 | void | ||
75 | vn_ioerror( | ||
76 | xfs_inode_t *ip, | ||
77 | int error, | ||
78 | char *f, | ||
79 | int l) | ||
80 | { | ||
81 | if (unlikely(error == -ENODEV)) | ||
82 | xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l); | ||
83 | } | ||
84 | |||
85 | #ifdef XFS_INODE_TRACE | ||
86 | |||
87 | /* | ||
88 | * Reference count of Linux inode if present, -1 if the xfs_inode | ||
89 | * has no associated Linux inode. | ||
90 | */ | ||
91 | static inline int xfs_icount(struct xfs_inode *ip) | ||
92 | { | ||
93 | struct inode *vp = VFS_I(ip); | ||
94 | |||
95 | if (vp) | ||
96 | return vn_count(vp); | ||
97 | return -1; | ||
98 | } | ||
99 | |||
100 | #define KTRACE_ENTER(ip, vk, s, line, ra) \ | ||
101 | ktrace_enter( (ip)->i_trace, \ | ||
102 | /* 0 */ (void *)(__psint_t)(vk), \ | ||
103 | /* 1 */ (void *)(s), \ | ||
104 | /* 2 */ (void *)(__psint_t) line, \ | ||
105 | /* 3 */ (void *)(__psint_t)xfs_icount(ip), \ | ||
106 | /* 4 */ (void *)(ra), \ | ||
107 | /* 5 */ NULL, \ | ||
108 | /* 6 */ (void *)(__psint_t)current_cpu(), \ | ||
109 | /* 7 */ (void *)(__psint_t)current_pid(), \ | ||
110 | /* 8 */ (void *)__return_address, \ | ||
111 | /* 9 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL) | ||
112 | |||
113 | /* | ||
114 | * Vnode tracing code. | ||
115 | */ | ||
116 | void | ||
117 | _xfs_itrace_entry(xfs_inode_t *ip, const char *func, inst_t *ra) | ||
118 | { | ||
119 | KTRACE_ENTER(ip, INODE_KTRACE_ENTRY, func, 0, ra); | ||
120 | } | ||
121 | |||
122 | void | ||
123 | _xfs_itrace_exit(xfs_inode_t *ip, const char *func, inst_t *ra) | ||
124 | { | ||
125 | KTRACE_ENTER(ip, INODE_KTRACE_EXIT, func, 0, ra); | ||
126 | } | ||
127 | |||
128 | void | ||
129 | xfs_itrace_hold(xfs_inode_t *ip, char *file, int line, inst_t *ra) | ||
130 | { | ||
131 | KTRACE_ENTER(ip, INODE_KTRACE_HOLD, file, line, ra); | ||
132 | } | ||
133 | |||
134 | void | ||
135 | _xfs_itrace_ref(xfs_inode_t *ip, char *file, int line, inst_t *ra) | ||
136 | { | ||
137 | KTRACE_ENTER(ip, INODE_KTRACE_REF, file, line, ra); | ||
138 | } | ||
139 | |||
140 | void | ||
141 | xfs_itrace_rele(xfs_inode_t *ip, char *file, int line, inst_t *ra) | ||
142 | { | ||
143 | KTRACE_ENTER(ip, INODE_KTRACE_RELE, file, line, ra); | ||
144 | } | ||
145 | #endif /* XFS_INODE_TRACE */ | ||
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 683ce16210ff..f65983a230d3 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h | |||
@@ -18,7 +18,10 @@ | |||
18 | #ifndef __XFS_VNODE_H__ | 18 | #ifndef __XFS_VNODE_H__ |
19 | #define __XFS_VNODE_H__ | 19 | #define __XFS_VNODE_H__ |
20 | 20 | ||
21 | #include "xfs_fs.h" | ||
22 | |||
21 | struct file; | 23 | struct file; |
24 | struct xfs_inode; | ||
22 | struct xfs_iomap; | 25 | struct xfs_iomap; |
23 | struct attrlist_cursor_kern; | 26 | struct attrlist_cursor_kern; |
24 | 27 | ||
@@ -51,40 +54,6 @@ struct attrlist_cursor_kern; | |||
51 | Prevent VM access to the pages until | 54 | Prevent VM access to the pages until |
52 | the operation completes. */ | 55 | the operation completes. */ |
53 | 56 | ||
54 | |||
55 | extern void vn_init(void); | ||
56 | |||
57 | /* | ||
58 | * Yeah, these don't take vnode anymore at all, all this should be | ||
59 | * cleaned up at some point. | ||
60 | */ | ||
61 | extern void vn_iowait(struct xfs_inode *ip); | ||
62 | extern void vn_iowake(struct xfs_inode *ip); | ||
63 | extern void vn_ioerror(struct xfs_inode *ip, int error, char *f, int l); | ||
64 | |||
65 | static inline int vn_count(struct inode *vp) | ||
66 | { | ||
67 | return atomic_read(&vp->i_count); | ||
68 | } | ||
69 | |||
70 | #define IHOLD(ip) \ | ||
71 | do { \ | ||
72 | ASSERT(atomic_read(&VFS_I(ip)->i_count) > 0) ; \ | ||
73 | atomic_inc(&(VFS_I(ip)->i_count)); \ | ||
74 | xfs_itrace_hold((ip), __FILE__, __LINE__, (inst_t *)__return_address); \ | ||
75 | } while (0) | ||
76 | |||
77 | #define IRELE(ip) \ | ||
78 | do { \ | ||
79 | xfs_itrace_rele((ip), __FILE__, __LINE__, (inst_t *)__return_address); \ | ||
80 | iput(VFS_I(ip)); \ | ||
81 | } while (0) | ||
82 | |||
83 | static inline struct inode *vn_grab(struct inode *vp) | ||
84 | { | ||
85 | return igrab(vp); | ||
86 | } | ||
87 | |||
88 | /* | 57 | /* |
89 | * Dealing with bad inodes | 58 | * Dealing with bad inodes |
90 | */ | 59 | */ |
@@ -121,39 +90,4 @@ static inline void vn_atime_to_time_t(struct inode *vp, time_t *tt) | |||
121 | PAGECACHE_TAG_DIRTY) | 90 | PAGECACHE_TAG_DIRTY) |
122 | 91 | ||
123 | 92 | ||
124 | /* | ||
125 | * Tracking vnode activity. | ||
126 | */ | ||
127 | #if defined(XFS_INODE_TRACE) | ||
128 | |||
129 | #define INODE_TRACE_SIZE 16 /* number of trace entries */ | ||
130 | #define INODE_KTRACE_ENTRY 1 | ||
131 | #define INODE_KTRACE_EXIT 2 | ||
132 | #define INODE_KTRACE_HOLD 3 | ||
133 | #define INODE_KTRACE_REF 4 | ||
134 | #define INODE_KTRACE_RELE 5 | ||
135 | |||
136 | extern void _xfs_itrace_entry(struct xfs_inode *, const char *, inst_t *); | ||
137 | extern void _xfs_itrace_exit(struct xfs_inode *, const char *, inst_t *); | ||
138 | extern void xfs_itrace_hold(struct xfs_inode *, char *, int, inst_t *); | ||
139 | extern void _xfs_itrace_ref(struct xfs_inode *, char *, int, inst_t *); | ||
140 | extern void xfs_itrace_rele(struct xfs_inode *, char *, int, inst_t *); | ||
141 | #define xfs_itrace_entry(ip) \ | ||
142 | _xfs_itrace_entry(ip, __func__, (inst_t *)__return_address) | ||
143 | #define xfs_itrace_exit(ip) \ | ||
144 | _xfs_itrace_exit(ip, __func__, (inst_t *)__return_address) | ||
145 | #define xfs_itrace_exit_tag(ip, tag) \ | ||
146 | _xfs_itrace_exit(ip, tag, (inst_t *)__return_address) | ||
147 | #define xfs_itrace_ref(ip) \ | ||
148 | _xfs_itrace_ref(ip, __FILE__, __LINE__, (inst_t *)__return_address) | ||
149 | |||
150 | #else | ||
151 | #define xfs_itrace_entry(a) | ||
152 | #define xfs_itrace_exit(a) | ||
153 | #define xfs_itrace_exit_tag(a, b) | ||
154 | #define xfs_itrace_hold(a, b, c, d) | ||
155 | #define xfs_itrace_ref(a) | ||
156 | #define xfs_itrace_rele(a, b, c, d) | ||
157 | #endif | ||
158 | |||
159 | #endif /* __XFS_VNODE_H__ */ | 93 | #endif /* __XFS_VNODE_H__ */ |