@@ -852,6 +852,192 @@ static inline bool xfs_file_sync_writes(struct file *filp)
852852 return false;
853853}
854854
855+ static int
856+ xfs_falloc_newsize (
857+ struct file * file ,
858+ int mode ,
859+ loff_t offset ,
860+ loff_t len ,
861+ loff_t * new_size )
862+ {
863+ struct inode * inode = file_inode (file );
864+
865+ if ((mode & FALLOC_FL_KEEP_SIZE ) || offset + len <= i_size_read (inode ))
866+ return 0 ;
867+ * new_size = offset + len ;
868+ return inode_newsize_ok (inode , * new_size );
869+ }
870+
871+ static int
872+ xfs_falloc_setsize (
873+ struct file * file ,
874+ loff_t new_size )
875+ {
876+ struct iattr iattr = {
877+ .ia_valid = ATTR_SIZE ,
878+ .ia_size = new_size ,
879+ };
880+
881+ if (!new_size )
882+ return 0 ;
883+ return xfs_vn_setattr_size (file_mnt_idmap (file ), file_dentry (file ),
884+ & iattr );
885+ }
886+
887+ static int
888+ xfs_falloc_collapse_range (
889+ struct file * file ,
890+ loff_t offset ,
891+ loff_t len )
892+ {
893+ struct inode * inode = file_inode (file );
894+ loff_t new_size = i_size_read (inode ) - len ;
895+ int error ;
896+
897+ if (!xfs_is_falloc_aligned (XFS_I (inode ), offset , len ))
898+ return - EINVAL ;
899+
900+ /*
901+ * There is no need to overlap collapse range with EOF, in which case it
902+ * is effectively a truncate operation
903+ */
904+ if (offset + len >= i_size_read (inode ))
905+ return - EINVAL ;
906+
907+ error = xfs_collapse_file_space (XFS_I (inode ), offset , len );
908+ if (error )
909+ return error ;
910+ return xfs_falloc_setsize (file , new_size );
911+ }
912+
913+ static int
914+ xfs_falloc_insert_range (
915+ struct file * file ,
916+ loff_t offset ,
917+ loff_t len )
918+ {
919+ struct inode * inode = file_inode (file );
920+ loff_t isize = i_size_read (inode );
921+ int error ;
922+
923+ if (!xfs_is_falloc_aligned (XFS_I (inode ), offset , len ))
924+ return - EINVAL ;
925+
926+ /*
927+ * New inode size must not exceed ->s_maxbytes, accounting for
928+ * possible signed overflow.
929+ */
930+ if (inode -> i_sb -> s_maxbytes - isize < len )
931+ return - EFBIG ;
932+
933+ /* Offset should be less than i_size */
934+ if (offset >= isize )
935+ return - EINVAL ;
936+
937+ error = xfs_falloc_setsize (file , isize + len );
938+ if (error )
939+ return error ;
940+
941+ /*
942+ * Perform hole insertion now that the file size has been updated so
943+ * that if we crash during the operation we don't leave shifted extents
944+ * past EOF and hence losing access to the data that is contained within
945+ * them.
946+ */
947+ return xfs_insert_file_space (XFS_I (inode ), offset , len );
948+ }
949+
950+ /*
951+ * Punch a hole and prealloc the range. We use a hole punch rather than
952+ * unwritten extent conversion for two reasons:
953+ *
954+ * 1.) Hole punch handles partial block zeroing for us.
955+ * 2.) If prealloc returns ENOSPC, the file range is still zero-valued by
956+ * virtue of the hole punch.
957+ */
958+ static int
959+ xfs_falloc_zero_range (
960+ struct file * file ,
961+ int mode ,
962+ loff_t offset ,
963+ loff_t len )
964+ {
965+ struct inode * inode = file_inode (file );
966+ unsigned int blksize = i_blocksize (inode );
967+ loff_t new_size = 0 ;
968+ int error ;
969+
970+ trace_xfs_zero_file_space (XFS_I (inode ));
971+
972+ error = xfs_falloc_newsize (file , mode , offset , len , & new_size );
973+ if (error )
974+ return error ;
975+
976+ error = xfs_free_file_space (XFS_I (inode ), offset , len );
977+ if (error )
978+ return error ;
979+
980+ len = round_up (offset + len , blksize ) - round_down (offset , blksize );
981+ offset = round_down (offset , blksize );
982+ error = xfs_alloc_file_space (XFS_I (inode ), offset , len );
983+ if (error )
984+ return error ;
985+ return xfs_falloc_setsize (file , new_size );
986+ }
987+
988+ static int
989+ xfs_falloc_unshare_range (
990+ struct file * file ,
991+ int mode ,
992+ loff_t offset ,
993+ loff_t len )
994+ {
995+ struct inode * inode = file_inode (file );
996+ loff_t new_size = 0 ;
997+ int error ;
998+
999+ error = xfs_falloc_newsize (file , mode , offset , len , & new_size );
1000+ if (error )
1001+ return error ;
1002+
1003+ error = xfs_reflink_unshare (XFS_I (inode ), offset , len );
1004+ if (error )
1005+ return error ;
1006+
1007+ error = xfs_alloc_file_space (XFS_I (inode ), offset , len );
1008+ if (error )
1009+ return error ;
1010+ return xfs_falloc_setsize (file , new_size );
1011+ }
1012+
1013+ static int
1014+ xfs_falloc_allocate_range (
1015+ struct file * file ,
1016+ int mode ,
1017+ loff_t offset ,
1018+ loff_t len )
1019+ {
1020+ struct inode * inode = file_inode (file );
1021+ loff_t new_size = 0 ;
1022+ int error ;
1023+
1024+ /*
1025+ * If always_cow mode we can't use preallocations and thus should not
1026+ * create them.
1027+ */
1028+ if (xfs_is_always_cow_inode (XFS_I (inode )))
1029+ return - EOPNOTSUPP ;
1030+
1031+ error = xfs_falloc_newsize (file , mode , offset , len , & new_size );
1032+ if (error )
1033+ return error ;
1034+
1035+ error = xfs_alloc_file_space (XFS_I (inode ), offset , len );
1036+ if (error )
1037+ return error ;
1038+ return xfs_falloc_setsize (file , new_size );
1039+ }
1040+
8551041#define XFS_FALLOC_FL_SUPPORTED \
8561042 (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \
8571043 FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | \
@@ -868,8 +1054,6 @@ xfs_file_fallocate(
8681054 struct xfs_inode * ip = XFS_I (inode );
8691055 long error ;
8701056 uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL ;
871- loff_t new_size = 0 ;
872- bool do_file_insert = false;
8731057
8741058 if (!S_ISREG (inode -> i_mode ))
8751059 return - EINVAL ;
@@ -894,129 +1078,31 @@ xfs_file_fallocate(
8941078 if (error )
8951079 goto out_unlock ;
8961080
897- if (mode & FALLOC_FL_PUNCH_HOLE ) {
1081+ switch (mode & FALLOC_FL_MODE_MASK ) {
1082+ case FALLOC_FL_PUNCH_HOLE :
8981083 error = xfs_free_file_space (ip , offset , len );
899- if (error )
900- goto out_unlock ;
901- } else if (mode & FALLOC_FL_COLLAPSE_RANGE ) {
902- if (!xfs_is_falloc_aligned (ip , offset , len )) {
903- error = - EINVAL ;
904- goto out_unlock ;
905- }
906-
907- /*
908- * There is no need to overlap collapse range with EOF,
909- * in which case it is effectively a truncate operation
910- */
911- if (offset + len >= i_size_read (inode )) {
912- error = - EINVAL ;
913- goto out_unlock ;
914- }
915-
916- new_size = i_size_read (inode ) - len ;
917-
918- error = xfs_collapse_file_space (ip , offset , len );
919- if (error )
920- goto out_unlock ;
921- } else if (mode & FALLOC_FL_INSERT_RANGE ) {
922- loff_t isize = i_size_read (inode );
923-
924- if (!xfs_is_falloc_aligned (ip , offset , len )) {
925- error = - EINVAL ;
926- goto out_unlock ;
927- }
928-
929- /*
930- * New inode size must not exceed ->s_maxbytes, accounting for
931- * possible signed overflow.
932- */
933- if (inode -> i_sb -> s_maxbytes - isize < len ) {
934- error = - EFBIG ;
935- goto out_unlock ;
936- }
937- new_size = isize + len ;
938-
939- /* Offset should be less than i_size */
940- if (offset >= isize ) {
941- error = - EINVAL ;
942- goto out_unlock ;
943- }
944- do_file_insert = true;
945- } else {
946- if (!(mode & FALLOC_FL_KEEP_SIZE ) &&
947- offset + len > i_size_read (inode )) {
948- new_size = offset + len ;
949- error = inode_newsize_ok (inode , new_size );
950- if (error )
951- goto out_unlock ;
952- }
953-
954- if (mode & FALLOC_FL_ZERO_RANGE ) {
955- /*
956- * Punch a hole and prealloc the range. We use a hole
957- * punch rather than unwritten extent conversion for two
958- * reasons:
959- *
960- * 1.) Hole punch handles partial block zeroing for us.
961- * 2.) If prealloc returns ENOSPC, the file range is
962- * still zero-valued by virtue of the hole punch.
963- */
964- unsigned int blksize = i_blocksize (inode );
965-
966- trace_xfs_zero_file_space (ip );
967-
968- error = xfs_free_file_space (ip , offset , len );
969- if (error )
970- goto out_unlock ;
971-
972- len = round_up (offset + len , blksize ) -
973- round_down (offset , blksize );
974- offset = round_down (offset , blksize );
975- } else if (mode & FALLOC_FL_UNSHARE_RANGE ) {
976- error = xfs_reflink_unshare (ip , offset , len );
977- if (error )
978- goto out_unlock ;
979- } else {
980- /*
981- * If always_cow mode we can't use preallocations and
982- * thus should not create them.
983- */
984- if (xfs_is_always_cow_inode (ip )) {
985- error = - EOPNOTSUPP ;
986- goto out_unlock ;
987- }
988- }
989-
990- error = xfs_alloc_file_space (ip , offset , len );
991- if (error )
992- goto out_unlock ;
993- }
994-
995- /* Change file size if needed */
996- if (new_size ) {
997- struct iattr iattr ;
998-
999- iattr .ia_valid = ATTR_SIZE ;
1000- iattr .ia_size = new_size ;
1001- error = xfs_vn_setattr_size (file_mnt_idmap (file ),
1002- file_dentry (file ), & iattr );
1003- if (error )
1004- goto out_unlock ;
1005- }
1006-
1007- /*
1008- * Perform hole insertion now that the file size has been
1009- * updated so that if we crash during the operation we don't
1010- * leave shifted extents past EOF and hence losing access to
1011- * the data that is contained within them.
1012- */
1013- if (do_file_insert ) {
1014- error = xfs_insert_file_space (ip , offset , len );
1015- if (error )
1016- goto out_unlock ;
1084+ break ;
1085+ case FALLOC_FL_COLLAPSE_RANGE :
1086+ error = xfs_falloc_collapse_range (file , offset , len );
1087+ break ;
1088+ case FALLOC_FL_INSERT_RANGE :
1089+ error = xfs_falloc_insert_range (file , offset , len );
1090+ break ;
1091+ case FALLOC_FL_ZERO_RANGE :
1092+ error = xfs_falloc_zero_range (file , mode , offset , len );
1093+ break ;
1094+ case FALLOC_FL_UNSHARE_RANGE :
1095+ error = xfs_falloc_unshare_range (file , mode , offset , len );
1096+ break ;
1097+ case FALLOC_FL_ALLOCATE_RANGE :
1098+ error = xfs_falloc_allocate_range (file , mode , offset , len );
1099+ break ;
1100+ default :
1101+ error = - EOPNOTSUPP ;
1102+ break ;
10171103 }
10181104
1019- if (xfs_file_sync_writes (file ))
1105+ if (! error && xfs_file_sync_writes (file ))
10201106 error = xfs_log_force_inode (ip );
10211107
10221108out_unlock :
0 commit comments