Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fs: fork splice_file_range() from do_splice_direct()

In preparation of calling do_splice_direct() without file_start_write()
held, create a new helper splice_file_range(), to be called from context
of ->copy_file_range() methods instead of do_splice_direct().

Currently, the only difference is that splice_file_range() does not take
flags argument and that it asserts that file_start_write() is held, but
we factor out a common helper do_splice_direct_actor() that will be used
later.

Use the new helper from __ceph_copy_file_range(), that was incorrectly
passing to do_splice_direct() the copy flags argument as splice flags.
The value of copy flags in ceph is always 0, so it is a smenatic bug fix.

Move the declaration of both helpers to linux/splice.h.

Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Link: https://lore.kernel.org/r/20231130141624.3338942-2-amir73il@gmail.com
Acked-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Amir Goldstein and committed by
Christian Brauner
488e8f68 21b32e6a

+68 -37
+5 -4
fs/ceph/file.c
··· 12 12 #include <linux/falloc.h> 13 13 #include <linux/iversion.h> 14 14 #include <linux/ktime.h> 15 + #include <linux/splice.h> 15 16 16 17 #include "super.h" 17 18 #include "mds_client.h" ··· 3011 3010 * {read,write}_iter, which will get caps again. 3012 3011 */ 3013 3012 put_rd_wr_caps(src_ci, src_got, dst_ci, dst_got); 3014 - ret = do_splice_direct(src_file, &src_off, dst_file, 3015 - &dst_off, src_objlen, flags); 3013 + ret = splice_file_range(src_file, &src_off, dst_file, &dst_off, 3014 + src_objlen); 3016 3015 /* Abort on short copies or on error */ 3017 3016 if (ret < (long)src_objlen) { 3018 3017 doutc(cl, "Failed partial copy (%zd)\n", ret); ··· 3066 3065 */ 3067 3066 if (len && (len < src_ci->i_layout.object_size)) { 3068 3067 doutc(cl, "Final partial copy of %zu bytes\n", len); 3069 - bytes = do_splice_direct(src_file, &src_off, dst_file, 3070 - &dst_off, len, flags); 3068 + bytes = splice_file_range(src_file, &src_off, dst_file, 3069 + &dst_off, len); 3071 3070 if (bytes > 0) 3072 3071 ret += bytes; 3073 3072 else
+2 -4
fs/read_write.c
··· 1423 1423 struct file *file_out, loff_t pos_out, 1424 1424 size_t len, unsigned int flags) 1425 1425 { 1426 - lockdep_assert(file_write_started(file_out)); 1427 - 1428 - return do_splice_direct(file_in, &pos_in, file_out, &pos_out, 1429 - len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0); 1426 + return splice_file_range(file_in, &pos_in, file_out, &pos_out, 1427 + min_t(size_t, len, MAX_RW_COUNT)); 1430 1428 } 1431 1429 EXPORT_SYMBOL(generic_copy_file_range); 1432 1430
+53 -22
fs/splice.c
··· 1170 1170 file->f_op->splice_eof(file); 1171 1171 } 1172 1172 1173 + static long do_splice_direct_actor(struct file *in, loff_t *ppos, 1174 + struct file *out, loff_t *opos, 1175 + size_t len, unsigned int flags, 1176 + splice_direct_actor *actor) 1177 + { 1178 + struct splice_desc sd = { 1179 + .len = len, 1180 + .total_len = len, 1181 + .flags = flags, 1182 + .pos = *ppos, 1183 + .u.file = out, 1184 + .splice_eof = direct_file_splice_eof, 1185 + .opos = opos, 1186 + }; 1187 + long ret; 1188 + 1189 + if (unlikely(!(out->f_mode & FMODE_WRITE))) 1190 + return -EBADF; 1191 + 1192 + if (unlikely(out->f_flags & O_APPEND)) 1193 + return -EINVAL; 1194 + 1195 + ret = splice_direct_to_actor(in, &sd, actor); 1196 + if (ret > 0) 1197 + *ppos = sd.pos; 1198 + 1199 + return ret; 1200 + } 1173 1201 /** 1174 1202 * do_splice_direct - splices data directly between two files 1175 1203 * @in: file to splice from ··· 1218 1190 long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, 1219 1191 loff_t *opos, size_t len, unsigned int flags) 1220 1192 { 1221 - struct splice_desc sd = { 1222 - .len = len, 1223 - .total_len = len, 1224 - .flags = flags, 1225 - .pos = *ppos, 1226 - .u.file = out, 1227 - .splice_eof = direct_file_splice_eof, 1228 - .opos = opos, 1229 - }; 1230 - long ret; 1231 - 1232 - if (unlikely(!(out->f_mode & FMODE_WRITE))) 1233 - return -EBADF; 1234 - 1235 - if (unlikely(out->f_flags & O_APPEND)) 1236 - return -EINVAL; 1237 - 1238 - ret = splice_direct_to_actor(in, &sd, direct_splice_actor); 1239 - if (ret > 0) 1240 - *ppos = sd.pos; 1241 - 1242 - return ret; 1193 + return do_splice_direct_actor(in, ppos, out, opos, len, flags, 1194 + direct_splice_actor); 1243 1195 } 1244 1196 EXPORT_SYMBOL(do_splice_direct); 1197 + 1198 + /** 1199 + * splice_file_range - splices data between two files for copy_file_range() 1200 + * @in: file to splice from 1201 + * @ppos: input file offset 1202 + * @out: file to splice to 1203 + * @opos: output file offset 1204 + * @len: number of bytes to splice 1205 + * 1206 + * Description: 1207 + * For use by generic_copy_file_range() and ->copy_file_range() methods. 1208 + * 1209 + * Callers already called rw_verify_area() on the entire range. 1210 + */ 1211 + long splice_file_range(struct file *in, loff_t *ppos, struct file *out, 1212 + loff_t *opos, size_t len) 1213 + { 1214 + lockdep_assert(file_write_started(out)); 1215 + 1216 + return do_splice_direct_actor(in, ppos, out, opos, len, 0, 1217 + direct_splice_actor); 1218 + } 1219 + EXPORT_SYMBOL(splice_file_range); 1245 1220 1246 1221 static int wait_for_space(struct pipe_inode_info *pipe, unsigned flags) 1247 1222 {
-2
include/linux/fs.h
··· 3052 3052 size_t len, unsigned int flags); 3053 3053 extern ssize_t iter_file_splice_write(struct pipe_inode_info *, 3054 3054 struct file *, loff_t *, size_t, unsigned int); 3055 - extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, 3056 - loff_t *opos, size_t len, unsigned int flags); 3057 3055 3058 3056 3059 3057 extern void
+8 -5
include/linux/splice.h
··· 80 80 long vfs_splice_read(struct file *in, loff_t *ppos, 81 81 struct pipe_inode_info *pipe, size_t len, 82 82 unsigned int flags); 83 - extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *, 84 - splice_direct_actor *); 85 - extern long do_splice(struct file *in, loff_t *off_in, 86 - struct file *out, loff_t *off_out, 87 - size_t len, unsigned int flags); 83 + ssize_t splice_direct_to_actor(struct file *file, struct splice_desc *sd, 84 + splice_direct_actor *actor); 85 + long do_splice(struct file *in, loff_t *off_in, struct file *out, 86 + loff_t *off_out, size_t len, unsigned int flags); 87 + long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, 88 + loff_t *opos, size_t len, unsigned int flags); 89 + long splice_file_range(struct file *in, loff_t *ppos, struct file *out, 90 + loff_t *opos, size_t len); 88 91 89 92 extern long do_tee(struct file *in, struct file *out, size_t len, 90 93 unsigned int flags);