aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:59:33 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:59:33 -0400
commit60c9b2746f589b0b809582b0471cf30ad3ae439f (patch)
treedeb0169acb7f7b5b5ef721650de1e0c6f139823c /fs/xfs/linux-2.6
parent4750def52cb2c21732dda9aa1d43a07db37b0186 (diff)
parentf7c66ce3f70d8417de0cfb481ca4e5430382ec5d (diff)
Merge git://oss.sgi.com:8090/xfs/xfs-2.6
* git://oss.sgi.com:8090/xfs/xfs-2.6: [XFS] Add lockdep support for XFS [XFS] Fix race in xfs_write() b/w dmapi callout and direct I/O checks. [XFS] Get rid of redundant "required" in msg. [XFS] Export via a function xfs_buftarg_list for use by kdb/xfsidbg. [XFS] Remove unused ilen variable and references. [XFS] Fix to prevent the notorious 'NULL files' problem after a crash. [XFS] Fix race condition in xfs_write(). [XFS] Fix uquota and oquota enforcement problems. [XFS] propogate return codes from flush routines [XFS] Fix quotaon syscall failures for group enforcement requests. [XFS] Invalidate quotacheck when mounting without a quota type. [XFS] reducing the number of random number functions. [XFS] remove more misc. unused args [XFS] the "aendp" arg to xfs_dir2_data_freescan is always NULL, remove it. [XFS] The last argument "lsn" of xfs_trans_commit() is always called with
Diffstat (limited to 'fs/xfs/linux-2.6')
-rw-r--r--fs/xfs/linux-2.6/mrlock.h12
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c89
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c10
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h3
-rw-r--r--fs/xfs/linux-2.6/xfs_fs_subr.c21
-rw-r--r--fs/xfs/linux-2.6/xfs_fs_subr.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c163
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h2
8 files changed, 212 insertions, 90 deletions
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h
index af168a1a98c1..c110bb002665 100644
--- a/fs/xfs/linux-2.6/mrlock.h
+++ b/fs/xfs/linux-2.6/mrlock.h
@@ -43,6 +43,18 @@ static inline void mrupdate(mrlock_t *mrp)
43 mrp->mr_writer = 1; 43 mrp->mr_writer = 1;
44} 44}
45 45
46static inline void mraccess_nested(mrlock_t *mrp, int subclass)
47{
48 down_read_nested(&mrp->mr_lock, subclass);
49}
50
51static inline void mrupdate_nested(mrlock_t *mrp, int subclass)
52{
53 down_write_nested(&mrp->mr_lock, subclass);
54 mrp->mr_writer = 1;
55}
56
57
46static inline int mrtryaccess(mrlock_t *mrp) 58static inline int mrtryaccess(mrlock_t *mrp)
47{ 59{
48 return down_read_trylock(&mrp->mr_lock); 60 return down_read_trylock(&mrp->mr_lock);
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 143ffc851c9d..4475588e973a 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -141,9 +141,46 @@ xfs_destroy_ioend(
141} 141}
142 142
143/* 143/*
144 * Update on-disk file size now that data has been written to disk.
145 * The current in-memory file size is i_size. If a write is beyond
146 * eof io_new_size will be the intended file size until i_size is
147 * updated. If this write does not extend all the way to the valid
148 * file size then restrict this update to the end of the write.
149 */
150STATIC void
151xfs_setfilesize(
152 xfs_ioend_t *ioend)
153{
154 xfs_inode_t *ip;
155 xfs_fsize_t isize;
156 xfs_fsize_t bsize;
157
158 ip = xfs_vtoi(ioend->io_vnode);
159
160 ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
161 ASSERT(ioend->io_type != IOMAP_READ);
162
163 if (unlikely(ioend->io_error))
164 return;
165
166 bsize = ioend->io_offset + ioend->io_size;
167
168 xfs_ilock(ip, XFS_ILOCK_EXCL);
169
170 isize = MAX(ip->i_size, ip->i_iocore.io_new_size);
171 isize = MIN(isize, bsize);
172
173 if (ip->i_d.di_size < isize) {
174 ip->i_d.di_size = isize;
175 ip->i_update_core = 1;
176 ip->i_update_size = 1;
177 }
178
179 xfs_iunlock(ip, XFS_ILOCK_EXCL);
180}
181
182/*
144 * Buffered IO write completion for delayed allocate extents. 183 * Buffered IO write completion for delayed allocate extents.
145 * TODO: Update ondisk isize now that we know the file data
146 * has been flushed (i.e. the notorious "NULL file" problem).
147 */ 184 */
148STATIC void 185STATIC void
149xfs_end_bio_delalloc( 186xfs_end_bio_delalloc(
@@ -152,6 +189,7 @@ xfs_end_bio_delalloc(
152 xfs_ioend_t *ioend = 189 xfs_ioend_t *ioend =
153 container_of(work, xfs_ioend_t, io_work); 190 container_of(work, xfs_ioend_t, io_work);
154 191
192 xfs_setfilesize(ioend);
155 xfs_destroy_ioend(ioend); 193 xfs_destroy_ioend(ioend);
156} 194}
157 195
@@ -165,6 +203,7 @@ xfs_end_bio_written(
165 xfs_ioend_t *ioend = 203 xfs_ioend_t *ioend =
166 container_of(work, xfs_ioend_t, io_work); 204 container_of(work, xfs_ioend_t, io_work);
167 205
206 xfs_setfilesize(ioend);
168 xfs_destroy_ioend(ioend); 207 xfs_destroy_ioend(ioend);
169} 208}
170 209
@@ -184,8 +223,23 @@ xfs_end_bio_unwritten(
184 xfs_off_t offset = ioend->io_offset; 223 xfs_off_t offset = ioend->io_offset;
185 size_t size = ioend->io_size; 224 size_t size = ioend->io_size;
186 225
187 if (likely(!ioend->io_error)) 226 if (likely(!ioend->io_error)) {
188 bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL); 227 bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL);
228 xfs_setfilesize(ioend);
229 }
230 xfs_destroy_ioend(ioend);
231}
232
233/*
234 * IO read completion for regular, written extents.
235 */
236STATIC void
237xfs_end_bio_read(
238 struct work_struct *work)
239{
240 xfs_ioend_t *ioend =
241 container_of(work, xfs_ioend_t, io_work);
242
189 xfs_destroy_ioend(ioend); 243 xfs_destroy_ioend(ioend);
190} 244}
191 245
@@ -224,6 +278,8 @@ xfs_alloc_ioend(
224 INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten); 278 INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten);
225 else if (type == IOMAP_DELAY) 279 else if (type == IOMAP_DELAY)
226 INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc); 280 INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc);
281 else if (type == IOMAP_READ)
282 INIT_WORK(&ioend->io_work, xfs_end_bio_read);
227 else 283 else
228 INIT_WORK(&ioend->io_work, xfs_end_bio_written); 284 INIT_WORK(&ioend->io_work, xfs_end_bio_written);
229 285
@@ -913,7 +969,7 @@ xfs_page_state_convert(
913 bh = head = page_buffers(page); 969 bh = head = page_buffers(page);
914 offset = page_offset(page); 970 offset = page_offset(page);
915 flags = -1; 971 flags = -1;
916 type = 0; 972 type = IOMAP_READ;
917 973
918 /* TODO: cleanup count and page_dirty */ 974 /* TODO: cleanup count and page_dirty */
919 975
@@ -999,7 +1055,7 @@ xfs_page_state_convert(
999 * That means it must already have extents allocated 1055 * That means it must already have extents allocated
1000 * underneath it. Map the extent by reading it. 1056 * underneath it. Map the extent by reading it.
1001 */ 1057 */
1002 if (!iomap_valid || type != 0) { 1058 if (!iomap_valid || type != IOMAP_READ) {
1003 flags = BMAPI_READ; 1059 flags = BMAPI_READ;
1004 size = xfs_probe_cluster(inode, page, bh, 1060 size = xfs_probe_cluster(inode, page, bh,
1005 head, 1); 1061 head, 1);
@@ -1010,7 +1066,7 @@ xfs_page_state_convert(
1010 iomap_valid = xfs_iomap_valid(&iomap, offset); 1066 iomap_valid = xfs_iomap_valid(&iomap, offset);
1011 } 1067 }
1012 1068
1013 type = 0; 1069 type = IOMAP_READ;
1014 if (!test_and_set_bit(BH_Lock, &bh->b_state)) { 1070 if (!test_and_set_bit(BH_Lock, &bh->b_state)) {
1015 ASSERT(buffer_mapped(bh)); 1071 ASSERT(buffer_mapped(bh));
1016 if (iomap_valid) 1072 if (iomap_valid)
@@ -1356,12 +1412,21 @@ xfs_end_io_direct(
1356 * completion handler in the future, in which case all this can 1412 * completion handler in the future, in which case all this can
1357 * go away. 1413 * go away.
1358 */ 1414 */
1359 if (private && size > 0) { 1415 ioend->io_offset = offset;
1360 ioend->io_offset = offset; 1416 ioend->io_size = size;
1361 ioend->io_size = size; 1417 if (ioend->io_type == IOMAP_READ) {
1418 xfs_finish_ioend(ioend);
1419 } else if (private && size > 0) {
1362 xfs_finish_ioend(ioend); 1420 xfs_finish_ioend(ioend);
1363 } else { 1421 } else {
1364 xfs_destroy_ioend(ioend); 1422 /*
1423 * A direct I/O write ioend starts it's life in unwritten
1424 * state in case they map an unwritten extent. This write
1425 * didn't map an unwritten extent so switch it's completion
1426 * handler.
1427 */
1428 INIT_WORK(&ioend->io_work, xfs_end_bio_written);
1429 xfs_finish_ioend(ioend);
1365 } 1430 }
1366 1431
1367 /* 1432 /*
@@ -1392,15 +1457,15 @@ xfs_vm_direct_IO(
1392 if (error) 1457 if (error)
1393 return -error; 1458 return -error;
1394 1459
1395 iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
1396
1397 if (rw == WRITE) { 1460 if (rw == WRITE) {
1461 iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
1398 ret = blockdev_direct_IO_own_locking(rw, iocb, inode, 1462 ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
1399 iomap.iomap_target->bt_bdev, 1463 iomap.iomap_target->bt_bdev,
1400 iov, offset, nr_segs, 1464 iov, offset, nr_segs,
1401 xfs_get_blocks_direct, 1465 xfs_get_blocks_direct,
1402 xfs_end_io_direct); 1466 xfs_end_io_direct);
1403 } else { 1467 } else {
1468 iocb->private = xfs_alloc_ioend(inode, IOMAP_READ);
1404 ret = blockdev_direct_IO_no_locking(rw, iocb, inode, 1469 ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
1405 iomap.iomap_target->bt_bdev, 1470 iomap.iomap_target->bt_bdev,
1406 iov, offset, nr_segs, 1471 iov, offset, nr_segs,
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 69e9e80735d2..fe4f66a5af14 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -1426,7 +1426,7 @@ xfs_free_bufhash(
1426/* 1426/*
1427 * buftarg list for delwrite queue processing 1427 * buftarg list for delwrite queue processing
1428 */ 1428 */
1429LIST_HEAD(xfs_buftarg_list); 1429static LIST_HEAD(xfs_buftarg_list);
1430static DEFINE_SPINLOCK(xfs_buftarg_lock); 1430static DEFINE_SPINLOCK(xfs_buftarg_lock);
1431 1431
1432STATIC void 1432STATIC void
@@ -1867,3 +1867,11 @@ xfs_buf_terminate(void)
1867 ktrace_free(xfs_buf_trace_buf); 1867 ktrace_free(xfs_buf_trace_buf);
1868#endif 1868#endif
1869} 1869}
1870
1871#ifdef CONFIG_KDB_MODULES
1872struct list_head *
1873xfs_get_buftarg_list(void)
1874{
1875 return &xfs_buftarg_list;
1876}
1877#endif
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 9e8ef8fef39f..b6241f6201a5 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -411,6 +411,9 @@ extern void xfs_free_buftarg(xfs_buftarg_t *, int);
411extern void xfs_wait_buftarg(xfs_buftarg_t *); 411extern void xfs_wait_buftarg(xfs_buftarg_t *);
412extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); 412extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
413extern int xfs_flush_buftarg(xfs_buftarg_t *, int); 413extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
414#ifdef CONFIG_KDB_MODULES
415extern struct list_head *xfs_get_buftarg_list(void);
416#endif
414 417
415#define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev) 418#define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev)
416#define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev) 419#define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev)
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
index dc0562828e76..2eb87cd082af 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
@@ -35,7 +35,7 @@ fs_tosspages(
35 truncate_inode_pages(ip->i_mapping, first); 35 truncate_inode_pages(ip->i_mapping, first);
36} 36}
37 37
38void 38int
39fs_flushinval_pages( 39fs_flushinval_pages(
40 bhv_desc_t *bdp, 40 bhv_desc_t *bdp,
41 xfs_off_t first, 41 xfs_off_t first,
@@ -44,13 +44,16 @@ fs_flushinval_pages(
44{ 44{
45 bhv_vnode_t *vp = BHV_TO_VNODE(bdp); 45 bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
46 struct inode *ip = vn_to_inode(vp); 46 struct inode *ip = vn_to_inode(vp);
47 int ret = 0;
47 48
48 if (VN_CACHED(vp)) { 49 if (VN_CACHED(vp)) {
49 if (VN_TRUNC(vp)) 50 if (VN_TRUNC(vp))
50 VUNTRUNCATE(vp); 51 VUNTRUNCATE(vp);
51 filemap_write_and_wait(ip->i_mapping); 52 ret = filemap_write_and_wait(ip->i_mapping);
52 truncate_inode_pages(ip->i_mapping, first); 53 if (!ret)
54 truncate_inode_pages(ip->i_mapping, first);
53 } 55 }
56 return ret;
54} 57}
55 58
56int 59int
@@ -63,14 +66,18 @@ fs_flush_pages(
63{ 66{
64 bhv_vnode_t *vp = BHV_TO_VNODE(bdp); 67 bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
65 struct inode *ip = vn_to_inode(vp); 68 struct inode *ip = vn_to_inode(vp);
69 int ret = 0;
70 int ret2;
66 71
67 if (VN_DIRTY(vp)) { 72 if (VN_DIRTY(vp)) {
68 if (VN_TRUNC(vp)) 73 if (VN_TRUNC(vp))
69 VUNTRUNCATE(vp); 74 VUNTRUNCATE(vp);
70 filemap_fdatawrite(ip->i_mapping); 75 ret = filemap_fdatawrite(ip->i_mapping);
71 if (flags & XFS_B_ASYNC) 76 if (flags & XFS_B_ASYNC)
72 return 0; 77 return ret;
73 filemap_fdatawait(ip->i_mapping); 78 ret2 = filemap_fdatawait(ip->i_mapping);
79 if (!ret)
80 ret = ret2;
74 } 81 }
75 return 0; 82 return ret;
76} 83}
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.h b/fs/xfs/linux-2.6/xfs_fs_subr.h
index aee9ccdd18f7..c1b53118a303 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.h
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.h
@@ -23,7 +23,7 @@ extern int fs_noerr(void);
23extern int fs_nosys(void); 23extern int fs_nosys(void);
24extern void fs_noval(void); 24extern void fs_noval(void);
25extern void fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int); 25extern void fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
26extern void fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int); 26extern int fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
27extern int fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int); 27extern int fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int);
28 28
29#endif /* __XFS_FS_SUBR_H__ */ 29#endif /* __XFS_FS_SUBR_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 558076dd0752..86fb671a8bcc 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -191,7 +191,7 @@ xfs_read(
191 struct file *file = iocb->ki_filp; 191 struct file *file = iocb->ki_filp;
192 struct inode *inode = file->f_mapping->host; 192 struct inode *inode = file->f_mapping->host;
193 size_t size = 0; 193 size_t size = 0;
194 ssize_t ret; 194 ssize_t ret = 0;
195 xfs_fsize_t n; 195 xfs_fsize_t n;
196 xfs_inode_t *ip; 196 xfs_inode_t *ip;
197 xfs_mount_t *mp; 197 xfs_mount_t *mp;
@@ -224,7 +224,7 @@ xfs_read(
224 mp->m_rtdev_targp : mp->m_ddev_targp; 224 mp->m_rtdev_targp : mp->m_ddev_targp;
225 if ((*offset & target->bt_smask) || 225 if ((*offset & target->bt_smask) ||
226 (size & target->bt_smask)) { 226 (size & target->bt_smask)) {
227 if (*offset == ip->i_d.di_size) { 227 if (*offset == ip->i_size) {
228 return (0); 228 return (0);
229 } 229 }
230 return -XFS_ERROR(EINVAL); 230 return -XFS_ERROR(EINVAL);
@@ -263,9 +263,13 @@ xfs_read(
263 263
264 if (unlikely(ioflags & IO_ISDIRECT)) { 264 if (unlikely(ioflags & IO_ISDIRECT)) {
265 if (VN_CACHED(vp)) 265 if (VN_CACHED(vp))
266 bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)), 266 ret = bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
267 -1, FI_REMAPF_LOCKED); 267 -1, FI_REMAPF_LOCKED);
268 mutex_unlock(&inode->i_mutex); 268 mutex_unlock(&inode->i_mutex);
269 if (ret) {
270 xfs_iunlock(ip, XFS_IOLOCK_SHARED);
271 return ret;
272 }
269 } 273 }
270 274
271 xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore, 275 xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
@@ -383,9 +387,10 @@ xfs_splice_write(
383{ 387{
384 xfs_inode_t *ip = XFS_BHVTOI(bdp); 388 xfs_inode_t *ip = XFS_BHVTOI(bdp);
385 xfs_mount_t *mp = ip->i_mount; 389 xfs_mount_t *mp = ip->i_mount;
390 xfs_iocore_t *io = &ip->i_iocore;
386 ssize_t ret; 391 ssize_t ret;
387 struct inode *inode = outfilp->f_mapping->host; 392 struct inode *inode = outfilp->f_mapping->host;
388 xfs_fsize_t isize; 393 xfs_fsize_t isize, new_size;
389 394
390 XFS_STATS_INC(xs_write_calls); 395 XFS_STATS_INC(xs_write_calls);
391 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) 396 if (XFS_FORCED_SHUTDOWN(ip->i_mount))
@@ -406,6 +411,14 @@ xfs_splice_write(
406 return -error; 411 return -error;
407 } 412 }
408 } 413 }
414
415 new_size = *ppos + count;
416
417 xfs_ilock(ip, XFS_ILOCK_EXCL);
418 if (new_size > ip->i_size)
419 io->io_new_size = new_size;
420 xfs_iunlock(ip, XFS_ILOCK_EXCL);
421
409 xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore, 422 xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
410 pipe, count, *ppos, ioflags); 423 pipe, count, *ppos, ioflags);
411 ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags); 424 ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
@@ -416,14 +429,18 @@ xfs_splice_write(
416 if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize)) 429 if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize))
417 *ppos = isize; 430 *ppos = isize;
418 431
419 if (*ppos > ip->i_d.di_size) { 432 if (*ppos > ip->i_size) {
420 xfs_ilock(ip, XFS_ILOCK_EXCL); 433 xfs_ilock(ip, XFS_ILOCK_EXCL);
421 if (*ppos > ip->i_d.di_size) { 434 if (*ppos > ip->i_size)
422 ip->i_d.di_size = *ppos; 435 ip->i_size = *ppos;
423 i_size_write(inode, *ppos); 436 xfs_iunlock(ip, XFS_ILOCK_EXCL);
424 ip->i_update_core = 1; 437 }
425 ip->i_update_size = 1; 438
426 } 439 if (io->io_new_size) {
440 xfs_ilock(ip, XFS_ILOCK_EXCL);
441 io->io_new_size = 0;
442 if (ip->i_d.di_size > ip->i_size)
443 ip->i_d.di_size = ip->i_size;
427 xfs_iunlock(ip, XFS_ILOCK_EXCL); 444 xfs_iunlock(ip, XFS_ILOCK_EXCL);
428 } 445 }
429 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 446 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
@@ -644,7 +661,7 @@ xfs_write(
644 bhv_vrwlock_t locktype; 661 bhv_vrwlock_t locktype;
645 size_t ocount = 0, count; 662 size_t ocount = 0, count;
646 loff_t pos; 663 loff_t pos;
647 int need_i_mutex = 1, need_flush = 0; 664 int need_i_mutex;
648 665
649 XFS_STATS_INC(xs_write_calls); 666 XFS_STATS_INC(xs_write_calls);
650 667
@@ -669,39 +686,20 @@ xfs_write(
669 if (XFS_FORCED_SHUTDOWN(mp)) 686 if (XFS_FORCED_SHUTDOWN(mp))
670 return -EIO; 687 return -EIO;
671 688
672 if (ioflags & IO_ISDIRECT) {
673 xfs_buftarg_t *target =
674 (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
675 mp->m_rtdev_targp : mp->m_ddev_targp;
676
677 if ((pos & target->bt_smask) || (count & target->bt_smask))
678 return XFS_ERROR(-EINVAL);
679
680 if (!VN_CACHED(vp) && pos < i_size_read(inode))
681 need_i_mutex = 0;
682
683 if (VN_CACHED(vp))
684 need_flush = 1;
685 }
686
687relock: 689relock:
688 if (need_i_mutex) { 690 if (ioflags & IO_ISDIRECT) {
691 iolock = XFS_IOLOCK_SHARED;
692 locktype = VRWLOCK_WRITE_DIRECT;
693 need_i_mutex = 0;
694 } else {
689 iolock = XFS_IOLOCK_EXCL; 695 iolock = XFS_IOLOCK_EXCL;
690 locktype = VRWLOCK_WRITE; 696 locktype = VRWLOCK_WRITE;
691 697 need_i_mutex = 1;
692 mutex_lock(&inode->i_mutex); 698 mutex_lock(&inode->i_mutex);
693 } else {
694 iolock = XFS_IOLOCK_SHARED;
695 locktype = VRWLOCK_WRITE_DIRECT;
696 } 699 }
697 700
698 xfs_ilock(xip, XFS_ILOCK_EXCL|iolock); 701 xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
699 702
700 isize = i_size_read(inode);
701
702 if (file->f_flags & O_APPEND)
703 *offset = isize;
704
705start: 703start:
706 error = -generic_write_checks(file, &pos, &count, 704 error = -generic_write_checks(file, &pos, &count,
707 S_ISBLK(inode->i_mode)); 705 S_ISBLK(inode->i_mode));
@@ -710,13 +708,8 @@ start:
710 goto out_unlock_mutex; 708 goto out_unlock_mutex;
711 } 709 }
712 710
713 new_size = pos + count;
714 if (new_size > isize)
715 io->io_new_size = new_size;
716
717 if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) && 711 if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
718 !(ioflags & IO_INVIS) && !eventsent)) { 712 !(ioflags & IO_INVIS) && !eventsent)) {
719 loff_t savedsize = pos;
720 int dmflags = FILP_DELAY_FLAG(file); 713 int dmflags = FILP_DELAY_FLAG(file);
721 714
722 if (need_i_mutex) 715 if (need_i_mutex)
@@ -727,8 +720,7 @@ start:
727 pos, count, 720 pos, count,
728 dmflags, &locktype); 721 dmflags, &locktype);
729 if (error) { 722 if (error) {
730 xfs_iunlock(xip, iolock); 723 goto out_unlock_internal;
731 goto out_unlock_mutex;
732 } 724 }
733 xfs_ilock(xip, XFS_ILOCK_EXCL); 725 xfs_ilock(xip, XFS_ILOCK_EXCL);
734 eventsent = 1; 726 eventsent = 1;
@@ -740,12 +732,35 @@ start:
740 * event prevents another call to XFS_SEND_DATA, which is 732 * event prevents another call to XFS_SEND_DATA, which is
741 * what allows the size to change in the first place. 733 * what allows the size to change in the first place.
742 */ 734 */
743 if ((file->f_flags & O_APPEND) && savedsize != isize) { 735 if ((file->f_flags & O_APPEND) && pos != xip->i_size)
744 pos = isize = xip->i_d.di_size; 736 goto start;
737 }
738
739 if (ioflags & IO_ISDIRECT) {
740 xfs_buftarg_t *target =
741 (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
742 mp->m_rtdev_targp : mp->m_ddev_targp;
743
744 if ((pos & target->bt_smask) || (count & target->bt_smask)) {
745 xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
746 return XFS_ERROR(-EINVAL);
747 }
748
749 if (!need_i_mutex && (VN_CACHED(vp) || pos > xip->i_size)) {
750 xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
751 iolock = XFS_IOLOCK_EXCL;
752 locktype = VRWLOCK_WRITE;
753 need_i_mutex = 1;
754 mutex_lock(&inode->i_mutex);
755 xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
745 goto start; 756 goto start;
746 } 757 }
747 } 758 }
748 759
760 new_size = pos + count;
761 if (new_size > xip->i_size)
762 io->io_new_size = new_size;
763
749 if (likely(!(ioflags & IO_INVIS))) { 764 if (likely(!(ioflags & IO_INVIS))) {
750 file_update_time(file); 765 file_update_time(file);
751 xfs_ichgtime_fast(xip, inode, 766 xfs_ichgtime_fast(xip, inode,
@@ -761,11 +776,11 @@ start:
761 * to zero it out up to the new size. 776 * to zero it out up to the new size.
762 */ 777 */
763 778
764 if (pos > isize) { 779 if (pos > xip->i_size) {
765 error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, isize); 780 error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, xip->i_size);
766 if (error) { 781 if (error) {
767 xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock); 782 xfs_iunlock(xip, XFS_ILOCK_EXCL);
768 goto out_unlock_mutex; 783 goto out_unlock_internal;
769 } 784 }
770 } 785 }
771 xfs_iunlock(xip, XFS_ILOCK_EXCL); 786 xfs_iunlock(xip, XFS_ILOCK_EXCL);
@@ -785,8 +800,7 @@ start:
785 if (likely(!error)) 800 if (likely(!error))
786 error = -remove_suid(file->f_path.dentry); 801 error = -remove_suid(file->f_path.dentry);
787 if (unlikely(error)) { 802 if (unlikely(error)) {
788 xfs_iunlock(xip, iolock); 803 goto out_unlock_internal;
789 goto out_unlock_mutex;
790 } 804 }
791 } 805 }
792 806
@@ -795,11 +809,14 @@ retry:
795 current->backing_dev_info = mapping->backing_dev_info; 809 current->backing_dev_info = mapping->backing_dev_info;
796 810
797 if ((ioflags & IO_ISDIRECT)) { 811 if ((ioflags & IO_ISDIRECT)) {
798 if (need_flush) { 812 if (VN_CACHED(vp)) {
813 WARN_ON(need_i_mutex == 0);
799 xfs_inval_cached_trace(io, pos, -1, 814 xfs_inval_cached_trace(io, pos, -1,
800 ctooff(offtoct(pos)), -1); 815 ctooff(offtoct(pos)), -1);
801 bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)), 816 error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)),
802 -1, FI_REMAPF_LOCKED); 817 -1, FI_REMAPF_LOCKED);
818 if (error)
819 goto out_unlock_internal;
803 } 820 }
804 821
805 if (need_i_mutex) { 822 if (need_i_mutex) {
@@ -827,7 +844,6 @@ retry:
827 pos += ret; 844 pos += ret;
828 count -= ret; 845 count -= ret;
829 846
830 need_i_mutex = 1;
831 ioflags &= ~IO_ISDIRECT; 847 ioflags &= ~IO_ISDIRECT;
832 xfs_iunlock(xip, iolock); 848 xfs_iunlock(xip, iolock);
833 goto relock; 849 goto relock;
@@ -854,12 +870,12 @@ retry:
854 error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp, 870 error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
855 DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL, 871 DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
856 0, 0, 0); /* Delay flag intentionally unused */ 872 0, 0, 0); /* Delay flag intentionally unused */
857 if (error)
858 goto out_nounlocks;
859 if (need_i_mutex) 873 if (need_i_mutex)
860 mutex_lock(&inode->i_mutex); 874 mutex_lock(&inode->i_mutex);
861 xfs_rwlock(bdp, locktype); 875 xfs_rwlock(bdp, locktype);
862 pos = xip->i_d.di_size; 876 if (error)
877 goto out_unlock_internal;
878 pos = xip->i_size;
863 ret = 0; 879 ret = 0;
864 goto retry; 880 goto retry;
865 } 881 }
@@ -868,14 +884,10 @@ retry:
868 if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize)) 884 if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize))
869 *offset = isize; 885 *offset = isize;
870 886
871 if (*offset > xip->i_d.di_size) { 887 if (*offset > xip->i_size) {
872 xfs_ilock(xip, XFS_ILOCK_EXCL); 888 xfs_ilock(xip, XFS_ILOCK_EXCL);
873 if (*offset > xip->i_d.di_size) { 889 if (*offset > xip->i_size)
874 xip->i_d.di_size = *offset; 890 xip->i_size = *offset;
875 i_size_write(inode, *offset);
876 xip->i_update_core = 1;
877 xip->i_update_size = 1;
878 }
879 xfs_iunlock(xip, XFS_ILOCK_EXCL); 891 xfs_iunlock(xip, XFS_ILOCK_EXCL);
880 } 892 }
881 893
@@ -897,16 +909,31 @@ retry:
897 909
898 error = sync_page_range(inode, mapping, pos, ret); 910 error = sync_page_range(inode, mapping, pos, ret);
899 if (!error) 911 if (!error)
900 error = ret; 912 error = -ret;
901 return error; 913 if (need_i_mutex)
914 mutex_lock(&inode->i_mutex);
915 xfs_rwlock(bdp, locktype);
902 } 916 }
903 917
904 out_unlock_internal: 918 out_unlock_internal:
919 if (io->io_new_size) {
920 xfs_ilock(xip, XFS_ILOCK_EXCL);
921 io->io_new_size = 0;
922 /*
923 * If this was a direct or synchronous I/O that failed (such
924 * as ENOSPC) then part of the I/O may have been written to
925 * disk before the error occured. In this case the on-disk
926 * file size may have been adjusted beyond the in-memory file
927 * size and now needs to be truncated back.
928 */
929 if (xip->i_d.di_size > xip->i_size)
930 xip->i_d.di_size = xip->i_size;
931 xfs_iunlock(xip, XFS_ILOCK_EXCL);
932 }
905 xfs_rwunlock(bdp, locktype); 933 xfs_rwunlock(bdp, locktype);
906 out_unlock_mutex: 934 out_unlock_mutex:
907 if (need_i_mutex) 935 if (need_i_mutex)
908 mutex_unlock(&inode->i_mutex); 936 mutex_unlock(&inode->i_mutex);
909 out_nounlocks:
910 return -error; 937 return -error;
911} 938}
912 939
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index b76118cf4897..d1b2d01843d1 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -194,7 +194,7 @@ typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int,
194typedef void (*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int); 194typedef void (*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int);
195typedef void (*vop_vnode_change_t)(bhv_desc_t *, bhv_vchange_t, __psint_t); 195typedef void (*vop_vnode_change_t)(bhv_desc_t *, bhv_vchange_t, __psint_t);
196typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); 196typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
197typedef void (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); 197typedef int (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
198typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, 198typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t,
199 uint64_t, int); 199 uint64_t, int);
200typedef int (*vop_iflush_t)(bhv_desc_t *, int); 200typedef int (*vop_iflush_t)(bhv_desc_t *, int);