@@ -54,6 +54,18 @@ static inline int ext2_inode_is_fast_symlink(struct inode *inode)
54
54
inode -> i_blocks - ea_blocks == 0 );
55
55
}
56
56
57
+ static void ext2_truncate_blocks (struct inode * inode , loff_t offset );
58
+
59
+ static void ext2_write_failed (struct address_space * mapping , loff_t to )
60
+ {
61
+ struct inode * inode = mapping -> host ;
62
+
63
+ if (to > inode -> i_size ) {
64
+ truncate_pagecache (inode , to , inode -> i_size );
65
+ ext2_truncate_blocks (inode , inode -> i_size );
66
+ }
67
+ }
68
+
57
69
/*
58
70
* Called at the last iput() if i_nlink is zero.
59
71
*/
@@ -71,7 +83,7 @@ void ext2_delete_inode (struct inode * inode)
71
83
72
84
inode -> i_size = 0 ;
73
85
if (inode -> i_blocks )
74
- ext2_truncate (inode );
86
+ ext2_truncate_blocks (inode , 0 );
75
87
ext2_free_inode (inode );
76
88
77
89
return ;
@@ -757,31 +769,53 @@ int __ext2_write_begin(struct file *file, struct address_space *mapping,
757
769
loff_t pos , unsigned len , unsigned flags ,
758
770
struct page * * pagep , void * * fsdata )
759
771
{
760
- return block_write_begin (file , mapping , pos , len , flags , pagep , fsdata ,
761
- ext2_get_block );
772
+ return block_write_begin_newtrunc (file , mapping , pos , len , flags ,
773
+ pagep , fsdata , ext2_get_block );
762
774
}
763
775
764
776
static int
765
777
ext2_write_begin (struct file * file , struct address_space * mapping ,
766
778
loff_t pos , unsigned len , unsigned flags ,
767
779
struct page * * pagep , void * * fsdata )
768
780
{
781
+ int ret ;
782
+
769
783
* pagep = NULL ;
770
- return __ext2_write_begin (file , mapping , pos , len , flags , pagep ,fsdata );
784
+ ret = __ext2_write_begin (file , mapping , pos , len , flags , pagep , fsdata );
785
+ if (ret < 0 )
786
+ ext2_write_failed (mapping , pos + len );
787
+ return ret ;
788
+ }
789
+
790
+ static int ext2_write_end (struct file * file , struct address_space * mapping ,
791
+ loff_t pos , unsigned len , unsigned copied ,
792
+ struct page * page , void * fsdata )
793
+ {
794
+ int ret ;
795
+
796
+ ret = generic_write_end (file , mapping , pos , len , copied , page , fsdata );
797
+ if (ret < len )
798
+ ext2_write_failed (mapping , pos + len );
799
+ return ret ;
771
800
}
772
801
773
802
static int
774
803
ext2_nobh_write_begin (struct file * file , struct address_space * mapping ,
775
804
loff_t pos , unsigned len , unsigned flags ,
776
805
struct page * * pagep , void * * fsdata )
777
806
{
807
+ int ret ;
808
+
778
809
/*
779
810
* Dir-in-pagecache still uses ext2_write_begin. Would have to rework
780
811
* directory handling code to pass around offsets rather than struct
781
812
* pages in order to make this work easily.
782
813
*/
783
- return nobh_write_begin (file , mapping , pos , len , flags , pagep , fsdata ,
784
- ext2_get_block );
814
+ ret = nobh_write_begin_newtrunc (file , mapping , pos , len , flags , pagep ,
815
+ fsdata , ext2_get_block );
816
+ if (ret < 0 )
817
+ ext2_write_failed (mapping , pos + len );
818
+ return ret ;
785
819
}
786
820
787
821
static int ext2_nobh_writepage (struct page * page ,
@@ -800,10 +834,15 @@ ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
800
834
loff_t offset , unsigned long nr_segs )
801
835
{
802
836
struct file * file = iocb -> ki_filp ;
803
- struct inode * inode = file -> f_mapping -> host ;
804
-
805
- return blockdev_direct_IO (rw , iocb , inode , inode -> i_sb -> s_bdev , iov ,
806
- offset , nr_segs , ext2_get_block , NULL );
837
+ struct address_space * mapping = file -> f_mapping ;
838
+ struct inode * inode = mapping -> host ;
839
+ ssize_t ret ;
840
+
841
+ ret = blockdev_direct_IO_newtrunc (rw , iocb , inode , inode -> i_sb -> s_bdev ,
842
+ iov , offset , nr_segs , ext2_get_block , NULL );
843
+ if (ret < 0 && (rw & WRITE ))
844
+ ext2_write_failed (mapping , offset + iov_length (iov , nr_segs ));
845
+ return ret ;
807
846
}
808
847
809
848
static int
@@ -818,7 +857,7 @@ const struct address_space_operations ext2_aops = {
818
857
.writepage = ext2_writepage ,
819
858
.sync_page = block_sync_page ,
820
859
.write_begin = ext2_write_begin ,
821
- .write_end = generic_write_end ,
860
+ .write_end = ext2_write_end ,
822
861
.bmap = ext2_bmap ,
823
862
.direct_IO = ext2_direct_IO ,
824
863
.writepages = ext2_writepages ,
@@ -1027,7 +1066,7 @@ static void ext2_free_branches(struct inode *inode, __le32 *p, __le32 *q, int de
1027
1066
ext2_free_data (inode , p , q );
1028
1067
}
1029
1068
1030
- void ext2_truncate (struct inode * inode )
1069
+ static void __ext2_truncate_blocks (struct inode * inode , loff_t offset )
1031
1070
{
1032
1071
__le32 * i_data = EXT2_I (inode )-> i_data ;
1033
1072
struct ext2_inode_info * ei = EXT2_I (inode );
@@ -1039,27 +1078,8 @@ void ext2_truncate(struct inode *inode)
1039
1078
int n ;
1040
1079
long iblock ;
1041
1080
unsigned blocksize ;
1042
-
1043
- if (!(S_ISREG (inode -> i_mode ) || S_ISDIR (inode -> i_mode ) ||
1044
- S_ISLNK (inode -> i_mode )))
1045
- return ;
1046
- if (ext2_inode_is_fast_symlink (inode ))
1047
- return ;
1048
- if (IS_APPEND (inode ) || IS_IMMUTABLE (inode ))
1049
- return ;
1050
-
1051
1081
blocksize = inode -> i_sb -> s_blocksize ;
1052
- iblock = (inode -> i_size + blocksize - 1 )
1053
- >> EXT2_BLOCK_SIZE_BITS (inode -> i_sb );
1054
-
1055
- if (mapping_is_xip (inode -> i_mapping ))
1056
- xip_truncate_page (inode -> i_mapping , inode -> i_size );
1057
- else if (test_opt (inode -> i_sb , NOBH ))
1058
- nobh_truncate_page (inode -> i_mapping ,
1059
- inode -> i_size , ext2_get_block );
1060
- else
1061
- block_truncate_page (inode -> i_mapping ,
1062
- inode -> i_size , ext2_get_block );
1082
+ iblock = (offset + blocksize - 1 ) >> EXT2_BLOCK_SIZE_BITS (inode -> i_sb );
1063
1083
1064
1084
n = ext2_block_to_path (inode , iblock , offsets , NULL );
1065
1085
if (n == 0 )
@@ -1127,13 +1147,71 @@ void ext2_truncate(struct inode *inode)
1127
1147
ext2_discard_reservation (inode );
1128
1148
1129
1149
mutex_unlock (& ei -> truncate_mutex );
1150
+ }
1151
+
1152
+ static void ext2_truncate_blocks (struct inode * inode , loff_t offset )
1153
+ {
1154
+ /*
1155
+ * XXX: it seems like a bug here that we don't allow
1156
+ * IS_APPEND inode to have blocks-past-i_size trimmed off.
1157
+ * review and fix this.
1158
+ *
1159
+ * Also would be nice to be able to handle IO errors and such,
1160
+ * but that's probably too much to ask.
1161
+ */
1162
+ if (!(S_ISREG (inode -> i_mode ) || S_ISDIR (inode -> i_mode ) ||
1163
+ S_ISLNK (inode -> i_mode )))
1164
+ return ;
1165
+ if (ext2_inode_is_fast_symlink (inode ))
1166
+ return ;
1167
+ if (IS_APPEND (inode ) || IS_IMMUTABLE (inode ))
1168
+ return ;
1169
+ __ext2_truncate_blocks (inode , offset );
1170
+ }
1171
+
1172
+ int ext2_setsize (struct inode * inode , loff_t newsize )
1173
+ {
1174
+ loff_t oldsize ;
1175
+ int error ;
1176
+
1177
+ error = inode_newsize_ok (inode , newsize );
1178
+ if (error )
1179
+ return error ;
1180
+
1181
+ if (!(S_ISREG (inode -> i_mode ) || S_ISDIR (inode -> i_mode ) ||
1182
+ S_ISLNK (inode -> i_mode )))
1183
+ return - EINVAL ;
1184
+ if (ext2_inode_is_fast_symlink (inode ))
1185
+ return - EINVAL ;
1186
+ if (IS_APPEND (inode ) || IS_IMMUTABLE (inode ))
1187
+ return - EPERM ;
1188
+
1189
+ if (mapping_is_xip (inode -> i_mapping ))
1190
+ error = xip_truncate_page (inode -> i_mapping , newsize );
1191
+ else if (test_opt (inode -> i_sb , NOBH ))
1192
+ error = nobh_truncate_page (inode -> i_mapping ,
1193
+ newsize , ext2_get_block );
1194
+ else
1195
+ error = block_truncate_page (inode -> i_mapping ,
1196
+ newsize , ext2_get_block );
1197
+ if (error )
1198
+ return error ;
1199
+
1200
+ oldsize = inode -> i_size ;
1201
+ i_size_write (inode , newsize );
1202
+ truncate_pagecache (inode , oldsize , newsize );
1203
+
1204
+ __ext2_truncate_blocks (inode , newsize );
1205
+
1130
1206
inode -> i_mtime = inode -> i_ctime = CURRENT_TIME_SEC ;
1131
1207
if (inode_needs_sync (inode )) {
1132
1208
sync_mapping_buffers (inode -> i_mapping );
1133
1209
ext2_sync_inode (inode );
1134
1210
} else {
1135
1211
mark_inode_dirty (inode );
1136
1212
}
1213
+
1214
+ return 0 ;
1137
1215
}
1138
1216
1139
1217
static struct ext2_inode * ext2_get_inode (struct super_block * sb , ino_t ino ,
@@ -1474,8 +1552,15 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
1474
1552
if (error )
1475
1553
return error ;
1476
1554
}
1477
- error = inode_setattr (inode , iattr );
1478
- if (!error && (iattr -> ia_valid & ATTR_MODE ))
1555
+ if (iattr -> ia_valid & ATTR_SIZE ) {
1556
+ error = ext2_setsize (inode , iattr -> ia_size );
1557
+ if (error )
1558
+ return error ;
1559
+ }
1560
+ generic_setattr (inode , iattr );
1561
+ if (iattr -> ia_valid & ATTR_MODE )
1479
1562
error = ext2_acl_chmod (inode );
1563
+ mark_inode_dirty (inode );
1564
+
1480
1565
return error ;
1481
1566
}
0 commit comments