Commit 5565a9d884327ac45d49041f1b846dac273e110c
Committed by
Miklos Szeredi
1 parent
7c190c8b9c
fuse: optimize __fuse_direct_io()
__fuse_direct_io() allocates fuse-requests by calling fuse_get_req(fc, n). The patch calculates 'n' based on iov[] array. This is useful because allocating FUSE_MAX_PAGES_PER_REQ page pointers and descriptors for each fuse request would be waste of memory in case of iov-s of smaller size. Signed-off-by: Maxim Patlasov <mpatlasov@parallels.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Showing 1 changed file with 21 additions and 4 deletions Side-by-side Diff
fs/fuse/file.c
... | ... | @@ -1088,14 +1088,14 @@ |
1088 | 1088 | return 0; |
1089 | 1089 | } |
1090 | 1090 | |
1091 | - while (nbytes < *nbytesp && req->num_pages < FUSE_MAX_PAGES_PER_REQ) { | |
1091 | + while (nbytes < *nbytesp && req->num_pages < req->max_pages) { | |
1092 | 1092 | unsigned npages; |
1093 | 1093 | unsigned long user_addr = fuse_get_user_addr(ii); |
1094 | 1094 | unsigned offset = user_addr & ~PAGE_MASK; |
1095 | 1095 | size_t frag_size = fuse_get_frag_size(ii, *nbytesp - nbytes); |
1096 | 1096 | int ret; |
1097 | 1097 | |
1098 | - unsigned n = FUSE_MAX_PAGES_PER_REQ - req->num_pages; | |
1098 | + unsigned n = req->max_pages - req->num_pages; | |
1099 | 1099 | frag_size = min_t(size_t, frag_size, n << PAGE_SHIFT); |
1100 | 1100 | |
1101 | 1101 | npages = (frag_size + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; |
... | ... | @@ -1131,6 +1131,23 @@ |
1131 | 1131 | return 0; |
1132 | 1132 | } |
1133 | 1133 | |
1134 | +static inline int fuse_iter_npages(const struct iov_iter *ii_p) | |
1135 | +{ | |
1136 | + struct iov_iter ii = *ii_p; | |
1137 | + int npages = 0; | |
1138 | + | |
1139 | + while (iov_iter_count(&ii) && npages < FUSE_MAX_PAGES_PER_REQ) { | |
1140 | + unsigned long user_addr = fuse_get_user_addr(&ii); | |
1141 | + unsigned offset = user_addr & ~PAGE_MASK; | |
1142 | + size_t frag_size = iov_iter_single_seg_count(&ii); | |
1143 | + | |
1144 | + npages += (frag_size + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | |
1145 | + iov_iter_advance(&ii, frag_size); | |
1146 | + } | |
1147 | + | |
1148 | + return min(npages, FUSE_MAX_PAGES_PER_REQ); | |
1149 | +} | |
1150 | + | |
1134 | 1151 | static ssize_t __fuse_direct_io(struct file *file, const struct iovec *iov, |
1135 | 1152 | unsigned long nr_segs, size_t count, |
1136 | 1153 | loff_t *ppos, int write) |
... | ... | @@ -1145,7 +1162,7 @@ |
1145 | 1162 | |
1146 | 1163 | iov_iter_init(&ii, iov, nr_segs, count, 0); |
1147 | 1164 | |
1148 | - req = fuse_get_req(fc, FUSE_MAX_PAGES_PER_REQ); | |
1165 | + req = fuse_get_req(fc, fuse_iter_npages(&ii)); | |
1149 | 1166 | if (IS_ERR(req)) |
1150 | 1167 | return PTR_ERR(req); |
1151 | 1168 | |
... | ... | @@ -1180,7 +1197,7 @@ |
1180 | 1197 | break; |
1181 | 1198 | if (count) { |
1182 | 1199 | fuse_put_request(fc, req); |
1183 | - req = fuse_get_req(fc, FUSE_MAX_PAGES_PER_REQ); | |
1200 | + req = fuse_get_req(fc, fuse_iter_npages(&ii)); | |
1184 | 1201 | if (IS_ERR(req)) |
1185 | 1202 | break; |
1186 | 1203 | } |