aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/linux-2.6')
-rw-r--r--fs/xfs/linux-2.6/sv.h22
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c66
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h3
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c87
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h30
-rw-r--r--fs/xfs/linux-2.6/xfs_cred.h8
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c189
-rw-r--r--fs/xfs/linux-2.6/xfs_fs_subr.c23
-rw-r--r--fs/xfs/linux-2.6/xfs_globals.c8
-rw-r--r--fs/xfs/linux-2.6/xfs_globals.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c223
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.h82
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c849
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.h214
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c122
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h13
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c50
-rw-r--r--fs/xfs/linux-2.6/xfs_stats.c6
-rw-r--r--fs/xfs/linux-2.6/xfs_stats.h65
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c884
-rw-r--r--fs/xfs/linux-2.6/xfs_super.h15
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c762
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.h55
-rw-r--r--fs/xfs/linux-2.6/xfs_sysctl.c11
-rw-r--r--fs/xfs/linux-2.6/xfs_sysctl.h3
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h77
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c145
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h72
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 */ 35static 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
42static 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])
51static wait_queue_head_t xfs_ioend_wq[NVSYNC];
52
53void __init
54xfs_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
62void
63xfs_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
71STATIC void
72xfs_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
45STATIC void 79STATIC void
46xfs_count_page_state( 80xfs_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
330STATIC_INLINE int 368STATIC_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 {
43extern const struct address_space_operations xfs_address_space_operations; 43extern const struct address_space_operations xfs_address_space_operations;
44extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); 44extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int);
45 45
46extern void xfs_ioend_init(void);
47extern 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
633STATIC 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
633xfs_buf_t * 656xfs_buf_t *
634xfs_buf_read_flags( 657xfs_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 */
1056int 1074int
1057xfs_buf_iostart( 1075xfs_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); 1093void
1094xfs_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
1097STATIC_INLINE void 1109STATIC_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 *);
214extern void xfs_buf_unlock(xfs_buf_t *); 214extern void xfs_buf_unlock(xfs_buf_t *);
215 215
216/* Buffer Read and Write Routines */ 216/* Buffer Read and Write Routines */
217extern int xfs_bawrite(void *mp, xfs_buf_t *bp);
218extern void xfs_bdwrite(void *mp, xfs_buf_t *bp);
217extern void xfs_buf_ioend(xfs_buf_t *, int); 219extern void xfs_buf_ioend(xfs_buf_t *, int);
218extern void xfs_buf_ioerror(xfs_buf_t *, int); 220extern void xfs_buf_ioerror(xfs_buf_t *, int);
219extern int xfs_buf_iostart(xfs_buf_t *, xfs_buf_flags_t);
220extern int xfs_buf_iorequest(xfs_buf_t *); 221extern int xfs_buf_iorequest(xfs_buf_t *);
221extern int xfs_buf_iowait(xfs_buf_t *); 222extern int xfs_buf_iowait(xfs_buf_t *);
222extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, xfs_caddr_t, 223extern 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
369static 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
377static inline void xfs_buf_relse(xfs_buf_t *bp) 364static 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 */
421static 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 */
26typedef const struct cred cred_t; 26typedef const struct cred cred_t;
27 27
28extern cred_t *sys_cred;
29
30/* this is a hack.. (assumes sys_cred is the only cred_t in the system) */
31static 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
45static struct vm_operations_struct xfs_file_vm_ops; 46static struct vm_operations_struct xfs_file_vm_ops;
46 47
47STATIC_INLINE ssize_t 48STATIC ssize_t
48__xfs_file_read( 49xfs_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
64STATIC ssize_t 67STATIC ssize_t
65xfs_file_aio_read( 68xfs_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
74STATIC ssize_t
75xfs_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
84STATIC_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
101STATIC ssize_t 86STATIC ssize_t
102xfs_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
111STATIC ssize_t
112xfs_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
121STATIC ssize_t
122xfs_file_splice_read( 87xfs_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
133STATIC ssize_t
134xfs_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
145STATIC ssize_t 103STATIC 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
157STATIC ssize_t
158xfs_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
169STATIC int 120STATIC int
170xfs_file_open( 121xfs_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
132STATIC int
133xfs_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
179STATIC int 156STATIC 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
251STATIC long
252xfs_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
272STATIC long
273xfs_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
328const 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
347const struct file_operations xfs_dir_file_operations = { 263const 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; }
24int fs_nosys(void) { return ENOSYS; } 24int fs_nosys(void) { return ENOSYS; }
25void fs_noval(void) { return; } 25void 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 */
27void 31void
28xfs_tosspages( 32xfs_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
59int 63int
@@ -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
87int
88xfs_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 */
27xfs_param_t xfs_params = { 27xfs_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 */
50static cred_t sys_cred_val;
51cred_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
21extern uint64_t xfs_panic_mask; /* set to cause more panics */ 21extern uint64_t xfs_panic_mask; /* set to cause more panics */
22extern 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 */
71STATIC int 71int
72xfs_find_handle( 72xfs_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
252STATIC int 248int
253xfs_open_by_handle( 249xfs_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
366STATIC int 360int
367xfs_readlink_by_handle( 361xfs_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
504STATIC int 495int
505xfs_attrmulti_attr_get( 496xfs_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
533STATIC int 524int
534xfs_attrmulti_attr_set( 525xfs_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
563STATIC int 554int
564xfs_attrmulti_attr_remove( 555xfs_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
665STATIC int 656int
666xfs_ioc_space( 657xfs_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
1258STATIC int 1248STATIC int
1249xfs_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
1261STATIC int
1259xfs_ioc_getbmap( 1262xfs_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
1288STATIC int 1292STATIC int
1293xfs_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
1304STATIC int
1289xfs_ioc_getbmapx( 1305xfs_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
1329int 1333/*
1330xfs_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 */
1339long
1340xfs_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
21extern int
22xfs_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
30extern int
31xfs_find_handle(
32 unsigned int cmd,
33 xfs_fsop_handlereq_t *hreq);
34
35extern int
36xfs_open_by_handle(
37 xfs_mount_t *mp,
38 xfs_fsop_handlereq_t *hreq,
39 struct file *parfilp,
40 struct inode *parinode);
41
42extern int
43xfs_readlink_by_handle(
44 xfs_mount_t *mp,
45 xfs_fsop_handlereq_t *hreq,
46 struct inode *parinode);
47
48extern int
49xfs_attrmulti_attr_get(
50 struct inode *inode,
51 char *name,
52 char __user *ubuf,
53 __uint32_t *len,
54 __uint32_t flags);
55
56extern 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
64extern int
65xfs_attrmulti_attr_remove(
66 struct inode *inode,
67 char *name,
68 __uint32_t flags);
69
70extern long
71xfs_file_ioctl(
72 struct file *filp,
73 unsigned int cmd,
74 unsigned long p);
75
76extern long
77xfs_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 53STATIC int
54#define _PACKED __attribute__((packed)) 54xfs_compat_flock64_copyin(
55/* on ia32 l_start is on a 32-bit boundary */ 55 xfs_flock64_t *bf,
56typedef 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 */
77STATIC unsigned long
78xfs_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
96typedef struct compat_xfs_fsop_geom_v1 { 69STATIC int
97 __u32 blocksize; /* filesystem (data) block size */ 70xfs_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
122STATIC 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
132typedef struct compat_xfs_inogrp { 86STATIC int
133 __u64 xi_startino; /* starting inode number */ 87xfs_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
138STATIC 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
97STATIC int
98xfs_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
108STATIC int
109xfs_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 132STATIC int
133xfs_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 */
147STATIC int
148xfs_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
166typedef 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
171STATIC int xfs_bstime_store_compat( 178STATIC int
172 compat_xfs_bstime_t __user *p32, 179xfs_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
184typedef struct compat_xfs_bstat { 192/* Return 0 on success or positive error (to xfs_bulkstat()) */
185 __u64 bs_ino; /* inode number */ 193STATIC int
186 __u16 bs_mode; /* type and mode */ 194xfs_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
208STATIC 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 231STATIC int
239 232xfs_bulkstat_one_compat(
240typedef 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 */
255STATIC int 249STATIC int
256xfs_ioc_bulkstat_compat( 250xfs_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
322STATIC int
323xfs_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
326typedef 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 352STATIC int
336#define XFS_IOC_PATH_TO_FSHANDLE_32 \ 353xfs_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
347STATIC 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
423STATIC int
424xfs_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
370STATIC long 475STATIC int
371xfs_compat_ioctl( 476xfs_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
562STATIC int
563xfs_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
597out:
598 iput(inode);
599 return error;
600}
601
602long
603xfs_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;
472long
473xfs_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
481long 732 if (xfs_compat_handlereq_copyin(&hreq, arg))
482xfs_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
21extern long xfs_file_compat_ioctl(struct file *, unsigned, unsigned long); 21#include <linux/compat.h>
22extern 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
46typedef struct compat_xfs_bstime {
47 compat_time_t tv_sec; /* seconds */
48 __s32 tv_nsec; /* and nanoseconds */
49} compat_xfs_bstime_t;
50
51typedef 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
75typedef 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
89typedef 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 */
111typedef 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
123typedef 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 */
136typedef 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
145typedef 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
155typedef 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 */
166typedef 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
186typedef 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
212typedef 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 */
219typedef 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
224typedef 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 */
664STATIC int
665xfs_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
702STATIC int
703xfs_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
664static const struct inode_operations xfs_inode_operations = { 740static 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
676static const struct inode_operations xfs_dir_inode_operations = { 753static 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 */
770void 851void
771xfs_setup_inode( 852xfs_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
23extern const struct file_operations xfs_file_operations; 23extern const struct file_operations xfs_file_operations;
24extern const struct file_operations xfs_dir_file_operations; 24extern const struct file_operations xfs_dir_file_operations;
25extern const struct file_operations xfs_invis_file_operations;
26 25
27extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size); 26extern 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
718retry:
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:
855int 844int
856xfs_bdstrat_cb(struct xfs_buf *bp) 845xfs_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
71static struct quotactl_ops xfs_quotactl_operations; 71static struct quotactl_ops xfs_quotactl_operations;
72static struct super_operations xfs_super_operations; 72static struct super_operations xfs_super_operations;
73static kmem_zone_t *xfs_vnode_zone;
74static kmem_zone_t *xfs_ioend_zone; 73static kmem_zone_t *xfs_ioend_zone;
75mempool_t *xfs_ioend_pool; 74mempool_t *xfs_ioend_pool;
76 75
77STATIC struct xfs_mount_args *
78xfs_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 */
191STATIC int 171STATIC int
192xfs_parseargs( 172xfs_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) { 458done:
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
457done:
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 */
705STATIC int 758STATIC int
706xfs_open_devices( 759xfs_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 */
814void 866void
815xfsaild_wakeup( 867xfsaild_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
823int 875int
824xfsaild( 876xfsaild(
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
849int 901int
850xfsaild_start( 902xfsaild_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
860void 912void
861xfsaild_stop( 913xfsaild_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 */
869STATIC struct inode * 921STATIC struct inode *
870xfs_fs_alloc_inode( 922xfs_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 */
876STATIC void 933STATIC void
877xfs_fs_destroy_inode( 934xfs_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 */
883STATIC void 952STATIC void
884xfs_fs_inode_init_once( 953xfs_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
1005out_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 */
953STATIC void
954xfs_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 */
978STATIC void
979xfs_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
988void
989xfs_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 */
1003STATIC void
1004xfs_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
1013void
1014xfs_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
1025STATIC void
1026xfs_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
1038STATIC int
1039xfssyncd(
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
1086STATIC void 1030STATIC 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 */
1354STATIC void 1272STATIC 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 */
1427STATIC int
1428xfs_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 */
1573STATIC int 1345STATIC int
1574xfs_finish_flags( 1346xfs_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)
1945STATIC int __init 1670STATIC int __init
1946xfs_init_zones(void) 1671xfs_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
2100init_xfs_fs(void) 1817init_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)
35extern void xfs_qm_init(void); 24extern void xfs_qm_init(void);
36extern void xfs_qm_exit(void); 25extern 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
102extern __uint64_t xfs_max_file_offset(unsigned int); 90extern __uint64_t xfs_max_file_offset(unsigned int);
103 91
104extern void xfs_flush_inode(struct xfs_inode *);
105extern void xfs_flush_device(struct xfs_inode *);
106
107extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); 92extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
108 93
109extern const struct export_operations xfs_export_operations; 94extern 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 */
54STATIC int
55xfs_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
169int
170xfs_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
202STATIC int
203xfs_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
236int
237xfs_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 */
306int
307xfs_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
331STATIC void
332xfs_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 */
361void
362xfs_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 */
393STATIC void
394xfs_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 */
418STATIC void
419xfs_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
428void
429xfs_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 */
443STATIC void
444xfs_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
453void
454xfs_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 */
470STATIC void
471xfs_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
490STATIC int
491xfssyncd(
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
538int
539xfs_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
550void
551xfs_syncd_stop(
552 struct xfs_mount *mp)
553{
554 kthread_stop(mp->m_sync_task);
555}
556
557int
558xfs_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 */
623void
624xfs_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
640void
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
650void
651xfs_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
666STATIC void
667xfs_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
679restart:
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
746int
747xfs_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
21struct xfs_mount;
22
23typedef 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
36int xfs_syncd_init(struct xfs_mount *mp);
37void xfs_syncd_stop(struct xfs_mount *mp);
38
39int xfs_sync_inodes(struct xfs_mount *mp, int flags);
40int xfs_sync_fsdata(struct xfs_mount *mp, int flags);
41
42int xfs_quiesce_data(struct xfs_mount *mp);
43void xfs_quiesce_attr(struct xfs_mount *mp);
44
45void xfs_flush_inode(struct xfs_inode *ip);
46void xfs_flush_device(struct xfs_inode *ip);
47
48int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode);
49int xfs_reclaim_inodes(struct xfs_mount *mp, int noblock, int mode);
50
51void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
52void xfs_inode_clear_reclaim_tag(struct xfs_inode *ip);
53void __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
57static ctl_table xfs_table[] = { 57static 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
33typedef struct xfs_param { 33typedef 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 {
68enum { 67enum {
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
24struct inode;
25
26struct fid;
27struct cred;
28struct seq_file;
29struct super_block;
30struct xfs_inode;
31struct xfs_mount;
32struct xfs_mount_args;
33
34typedef struct kstatfs bhv_statvfs_t;
35
36typedef 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])
41static wait_queue_head_t vsync[NVSYNC];
42
43void __init
44vn_init(void)
45{
46 int i;
47
48 for (i = 0; i < NVSYNC; i++)
49 init_waitqueue_head(&vsync[i]);
50}
51
52void
53vn_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
61void
62vn_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 */
74void
75vn_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 */
91static 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 */
116void
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
122void
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
128void
129xfs_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
134void
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
140void
141xfs_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
21struct file; 23struct file;
24struct xfs_inode;
22struct xfs_iomap; 25struct xfs_iomap;
23struct attrlist_cursor_kern; 26struct 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
55extern 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 */
61extern void vn_iowait(struct xfs_inode *ip);
62extern void vn_iowake(struct xfs_inode *ip);
63extern void vn_ioerror(struct xfs_inode *ip, int error, char *f, int l);
64
65static inline int vn_count(struct inode *vp)
66{
67 return atomic_read(&vp->i_count);
68}
69
70#define IHOLD(ip) \
71do { \
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) \
78do { \
79 xfs_itrace_rele((ip), __FILE__, __LINE__, (inst_t *)__return_address); \
80 iput(VFS_I(ip)); \
81} while (0)
82
83static 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
136extern void _xfs_itrace_entry(struct xfs_inode *, const char *, inst_t *);
137extern void _xfs_itrace_exit(struct xfs_inode *, const char *, inst_t *);
138extern void xfs_itrace_hold(struct xfs_inode *, char *, int, inst_t *);
139extern void _xfs_itrace_ref(struct xfs_inode *, char *, int, inst_t *);
140extern 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__ */