summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-12 16:27:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-12 16:27:20 -0400
commit5f739e4a491ab63730ef3b7464171340c689fbff (patch)
tree0ebf797a2b43ebefac2e5d0ef113b12a57c2b964
parenta667cb7a94d48a483fb5d6006fe04a440f1a42ce (diff)
parent12e1e7af1a55b9f911025365af4c689b3933c22a (diff)
Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc vfs updates from Al Viro: "Assorted fixes (really no common topic here)" * 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: vfs: Make __vfs_write() static vfs: fix preadv64v2 and pwritev64v2 compat syscalls with offset == -1 pipe: stop using ->can_merge splice: don't merge into linked buffers fs: move generic stat response attr handling to vfs_getattr_nosec orangefs: don't reinitialize result_mask in ->getattr fs/devpts: always delete dcache dentry-s in dput()
-rw-r--r--fs/devpts/inode.c1
-rw-r--r--fs/orangefs/inode.c7
-rw-r--r--fs/pipe.c32
-rw-r--r--fs/read_write.c10
-rw-r--r--fs/splice.c8
-rw-r--r--fs/stat.c12
-rw-r--r--include/linux/pipe_fs_i.h8
-rw-r--r--kernel/relay.c1
-rw-r--r--kernel/trace/trace.c2
-rw-r--r--net/smc/smc_rx.c1
10 files changed, 52 insertions, 30 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index c53814539070..553a3f3300ae 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -455,6 +455,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
455 s->s_blocksize_bits = 10; 455 s->s_blocksize_bits = 10;
456 s->s_magic = DEVPTS_SUPER_MAGIC; 456 s->s_magic = DEVPTS_SUPER_MAGIC;
457 s->s_op = &devpts_sops; 457 s->s_op = &devpts_sops;
458 s->s_d_op = &simple_dentry_operations;
458 s->s_time_gran = 1; 459 s->s_time_gran = 1;
459 460
460 error = -ENOMEM; 461 error = -ENOMEM;
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index f038235c64bd..c3334eca18c7 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -261,11 +261,8 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
261 generic_fillattr(inode, stat); 261 generic_fillattr(inode, stat);
262 262
263 /* override block size reported to stat */ 263 /* override block size reported to stat */
264 if (request_mask & STATX_SIZE) 264 if (!(request_mask & STATX_SIZE))
265 stat->result_mask = STATX_BASIC_STATS; 265 stat->result_mask &= ~STATX_SIZE;
266 else
267 stat->result_mask = STATX_BASIC_STATS &
268 ~STATX_SIZE;
269 266
270 stat->attributes_mask = STATX_ATTR_IMMUTABLE | 267 stat->attributes_mask = STATX_ATTR_IMMUTABLE |
271 STATX_ATTR_APPEND; 268 STATX_ATTR_APPEND;
diff --git a/fs/pipe.c b/fs/pipe.c
index 51d5fd8840ab..070aad543382 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -225,8 +225,15 @@ void generic_pipe_buf_release(struct pipe_inode_info *pipe,
225} 225}
226EXPORT_SYMBOL(generic_pipe_buf_release); 226EXPORT_SYMBOL(generic_pipe_buf_release);
227 227
228/* New data written to a pipe may be appended to a buffer with this type. */
228static const struct pipe_buf_operations anon_pipe_buf_ops = { 229static const struct pipe_buf_operations anon_pipe_buf_ops = {
229 .can_merge = 1, 230 .confirm = generic_pipe_buf_confirm,
231 .release = anon_pipe_buf_release,
232 .steal = anon_pipe_buf_steal,
233 .get = generic_pipe_buf_get,
234};
235
236static const struct pipe_buf_operations anon_pipe_buf_nomerge_ops = {
230 .confirm = generic_pipe_buf_confirm, 237 .confirm = generic_pipe_buf_confirm,
231 .release = anon_pipe_buf_release, 238 .release = anon_pipe_buf_release,
232 .steal = anon_pipe_buf_steal, 239 .steal = anon_pipe_buf_steal,
@@ -234,13 +241,32 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {
234}; 241};
235 242
236static const struct pipe_buf_operations packet_pipe_buf_ops = { 243static const struct pipe_buf_operations packet_pipe_buf_ops = {
237 .can_merge = 0,
238 .confirm = generic_pipe_buf_confirm, 244 .confirm = generic_pipe_buf_confirm,
239 .release = anon_pipe_buf_release, 245 .release = anon_pipe_buf_release,
240 .steal = anon_pipe_buf_steal, 246 .steal = anon_pipe_buf_steal,
241 .get = generic_pipe_buf_get, 247 .get = generic_pipe_buf_get,
242}; 248};
243 249
250/**
251 * pipe_buf_mark_unmergeable - mark a &struct pipe_buffer as unmergeable
252 * @buf: the buffer to mark
253 *
254 * Description:
255 * This function ensures that no future writes will be merged into the
256 * given &struct pipe_buffer. This is necessary when multiple pipe buffers
257 * share the same backing page.
258 */
259void pipe_buf_mark_unmergeable(struct pipe_buffer *buf)
260{
261 if (buf->ops == &anon_pipe_buf_ops)
262 buf->ops = &anon_pipe_buf_nomerge_ops;
263}
264
265static bool pipe_buf_can_merge(struct pipe_buffer *buf)
266{
267 return buf->ops == &anon_pipe_buf_ops;
268}
269
244static ssize_t 270static ssize_t
245pipe_read(struct kiocb *iocb, struct iov_iter *to) 271pipe_read(struct kiocb *iocb, struct iov_iter *to)
246{ 272{
@@ -378,7 +404,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
378 struct pipe_buffer *buf = pipe->bufs + lastbuf; 404 struct pipe_buffer *buf = pipe->bufs + lastbuf;
379 int offset = buf->offset + buf->len; 405 int offset = buf->offset + buf->len;
380 406
381 if (buf->ops->can_merge && offset + chars <= PAGE_SIZE) { 407 if (pipe_buf_can_merge(buf) && offset + chars <= PAGE_SIZE) {
382 ret = pipe_buf_confirm(pipe, buf); 408 ret = pipe_buf_confirm(pipe, buf);
383 if (ret) 409 if (ret)
384 goto out; 410 goto out;
diff --git a/fs/read_write.c b/fs/read_write.c
index 30df848b7451..177ccc3d405a 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -478,8 +478,8 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t
478 return ret; 478 return ret;
479} 479}
480 480
481ssize_t __vfs_write(struct file *file, const char __user *p, size_t count, 481static ssize_t __vfs_write(struct file *file, const char __user *p,
482 loff_t *pos) 482 size_t count, loff_t *pos)
483{ 483{
484 if (file->f_op->write) 484 if (file->f_op->write)
485 return file->f_op->write(file, p, count, pos); 485 return file->f_op->write(file, p, count, pos);
@@ -1238,6 +1238,9 @@ COMPAT_SYSCALL_DEFINE5(preadv64v2, unsigned long, fd,
1238 const struct compat_iovec __user *,vec, 1238 const struct compat_iovec __user *,vec,
1239 unsigned long, vlen, loff_t, pos, rwf_t, flags) 1239 unsigned long, vlen, loff_t, pos, rwf_t, flags)
1240{ 1240{
1241 if (pos == -1)
1242 return do_compat_readv(fd, vec, vlen, flags);
1243
1241 return do_compat_preadv64(fd, vec, vlen, pos, flags); 1244 return do_compat_preadv64(fd, vec, vlen, pos, flags);
1242} 1245}
1243#endif 1246#endif
@@ -1344,6 +1347,9 @@ COMPAT_SYSCALL_DEFINE5(pwritev64v2, unsigned long, fd,
1344 const struct compat_iovec __user *,vec, 1347 const struct compat_iovec __user *,vec,
1345 unsigned long, vlen, loff_t, pos, rwf_t, flags) 1348 unsigned long, vlen, loff_t, pos, rwf_t, flags)
1346{ 1349{
1350 if (pos == -1)
1351 return do_compat_writev(fd, vec, vlen, flags);
1352
1347 return do_compat_pwritev64(fd, vec, vlen, pos, flags); 1353 return do_compat_pwritev64(fd, vec, vlen, pos, flags);
1348} 1354}
1349#endif 1355#endif
diff --git a/fs/splice.c b/fs/splice.c
index 6489fb9436e4..3ee7e82df48f 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -138,7 +138,6 @@ error:
138} 138}
139 139
140const struct pipe_buf_operations page_cache_pipe_buf_ops = { 140const struct pipe_buf_operations page_cache_pipe_buf_ops = {
141 .can_merge = 0,
142 .confirm = page_cache_pipe_buf_confirm, 141 .confirm = page_cache_pipe_buf_confirm,
143 .release = page_cache_pipe_buf_release, 142 .release = page_cache_pipe_buf_release,
144 .steal = page_cache_pipe_buf_steal, 143 .steal = page_cache_pipe_buf_steal,
@@ -156,7 +155,6 @@ static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
156} 155}
157 156
158static const struct pipe_buf_operations user_page_pipe_buf_ops = { 157static const struct pipe_buf_operations user_page_pipe_buf_ops = {
159 .can_merge = 0,
160 .confirm = generic_pipe_buf_confirm, 158 .confirm = generic_pipe_buf_confirm,
161 .release = page_cache_pipe_buf_release, 159 .release = page_cache_pipe_buf_release,
162 .steal = user_page_pipe_buf_steal, 160 .steal = user_page_pipe_buf_steal,
@@ -326,7 +324,6 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
326EXPORT_SYMBOL(generic_file_splice_read); 324EXPORT_SYMBOL(generic_file_splice_read);
327 325
328const struct pipe_buf_operations default_pipe_buf_ops = { 326const struct pipe_buf_operations default_pipe_buf_ops = {
329 .can_merge = 0,
330 .confirm = generic_pipe_buf_confirm, 327 .confirm = generic_pipe_buf_confirm,
331 .release = generic_pipe_buf_release, 328 .release = generic_pipe_buf_release,
332 .steal = generic_pipe_buf_steal, 329 .steal = generic_pipe_buf_steal,
@@ -341,7 +338,6 @@ static int generic_pipe_buf_nosteal(struct pipe_inode_info *pipe,
341 338
342/* Pipe buffer operations for a socket and similar. */ 339/* Pipe buffer operations for a socket and similar. */
343const struct pipe_buf_operations nosteal_pipe_buf_ops = { 340const struct pipe_buf_operations nosteal_pipe_buf_ops = {
344 .can_merge = 0,
345 .confirm = generic_pipe_buf_confirm, 341 .confirm = generic_pipe_buf_confirm,
346 .release = generic_pipe_buf_release, 342 .release = generic_pipe_buf_release,
347 .steal = generic_pipe_buf_nosteal, 343 .steal = generic_pipe_buf_nosteal,
@@ -1606,6 +1602,8 @@ retry:
1606 */ 1602 */
1607 obuf->flags &= ~PIPE_BUF_FLAG_GIFT; 1603 obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
1608 1604
1605 pipe_buf_mark_unmergeable(obuf);
1606
1609 obuf->len = len; 1607 obuf->len = len;
1610 opipe->nrbufs++; 1608 opipe->nrbufs++;
1611 ibuf->offset += obuf->len; 1609 ibuf->offset += obuf->len;
@@ -1680,6 +1678,8 @@ static int link_pipe(struct pipe_inode_info *ipipe,
1680 */ 1678 */
1681 obuf->flags &= ~PIPE_BUF_FLAG_GIFT; 1679 obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
1682 1680
1681 pipe_buf_mark_unmergeable(obuf);
1682
1683 if (obuf->len > len) 1683 if (obuf->len > len)
1684 obuf->len = len; 1684 obuf->len = len;
1685 1685
diff --git a/fs/stat.c b/fs/stat.c
index adbfcd86c81b..c38e4c2e1221 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -45,11 +45,6 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
45 stat->ctime = inode->i_ctime; 45 stat->ctime = inode->i_ctime;
46 stat->blksize = i_blocksize(inode); 46 stat->blksize = i_blocksize(inode);
47 stat->blocks = inode->i_blocks; 47 stat->blocks = inode->i_blocks;
48
49 if (IS_NOATIME(inode))
50 stat->result_mask &= ~STATX_ATIME;
51 if (IS_AUTOMOUNT(inode))
52 stat->attributes |= STATX_ATTR_AUTOMOUNT;
53} 48}
54EXPORT_SYMBOL(generic_fillattr); 49EXPORT_SYMBOL(generic_fillattr);
55 50
@@ -75,6 +70,13 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
75 stat->result_mask |= STATX_BASIC_STATS; 70 stat->result_mask |= STATX_BASIC_STATS;
76 request_mask &= STATX_ALL; 71 request_mask &= STATX_ALL;
77 query_flags &= KSTAT_QUERY_FLAGS; 72 query_flags &= KSTAT_QUERY_FLAGS;
73
74 /* allow the fs to override these if it really wants to */
75 if (IS_NOATIME(inode))
76 stat->result_mask &= ~STATX_ATIME;
77 if (IS_AUTOMOUNT(inode))
78 stat->attributes |= STATX_ATTR_AUTOMOUNT;
79
78 if (inode->i_op->getattr) 80 if (inode->i_op->getattr)
79 return inode->i_op->getattr(path, stat, request_mask, 81 return inode->i_op->getattr(path, stat, request_mask,
80 query_flags); 82 query_flags);
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 5a3bb3b7c9ad..787d224ff43e 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -74,13 +74,6 @@ struct pipe_inode_info {
74 */ 74 */
75struct pipe_buf_operations { 75struct pipe_buf_operations {
76 /* 76 /*
77 * This is set to 1, if the generic pipe read/write may coalesce
78 * data into an existing buffer. If this is set to 0, a new pipe
79 * page segment is always used for new data.
80 */
81 int can_merge;
82
83 /*
84 * ->confirm() verifies that the data in the pipe buffer is there 77 * ->confirm() verifies that the data in the pipe buffer is there
85 * and that the contents are good. If the pages in the pipe belong 78 * and that the contents are good. If the pages in the pipe belong
86 * to a file system, we may need to wait for IO completion in this 79 * to a file system, we may need to wait for IO completion in this
@@ -182,6 +175,7 @@ void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *);
182int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *); 175int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *);
183int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *); 176int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
184void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *); 177void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *);
178void pipe_buf_mark_unmergeable(struct pipe_buffer *buf);
185 179
186extern const struct pipe_buf_operations nosteal_pipe_buf_ops; 180extern const struct pipe_buf_operations nosteal_pipe_buf_ops;
187 181
diff --git a/kernel/relay.c b/kernel/relay.c
index 9e0f52375487..ade14fb7ce2e 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -1177,7 +1177,6 @@ static void relay_pipe_buf_release(struct pipe_inode_info *pipe,
1177} 1177}
1178 1178
1179static const struct pipe_buf_operations relay_pipe_buf_ops = { 1179static const struct pipe_buf_operations relay_pipe_buf_ops = {
1180 .can_merge = 0,
1181 .confirm = generic_pipe_buf_confirm, 1180 .confirm = generic_pipe_buf_confirm,
1182 .release = relay_pipe_buf_release, 1181 .release = relay_pipe_buf_release,
1183 .steal = generic_pipe_buf_steal, 1182 .steal = generic_pipe_buf_steal,
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index d7325eb1bc83..94ffc1c559d5 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6023,7 +6023,6 @@ static void tracing_spd_release_pipe(struct splice_pipe_desc *spd,
6023} 6023}
6024 6024
6025static const struct pipe_buf_operations tracing_pipe_buf_ops = { 6025static const struct pipe_buf_operations tracing_pipe_buf_ops = {
6026 .can_merge = 0,
6027 .confirm = generic_pipe_buf_confirm, 6026 .confirm = generic_pipe_buf_confirm,
6028 .release = generic_pipe_buf_release, 6027 .release = generic_pipe_buf_release,
6029 .steal = generic_pipe_buf_steal, 6028 .steal = generic_pipe_buf_steal,
@@ -7050,7 +7049,6 @@ static void buffer_pipe_buf_get(struct pipe_inode_info *pipe,
7050 7049
7051/* Pipe buffer operations for a buffer. */ 7050/* Pipe buffer operations for a buffer. */
7052static const struct pipe_buf_operations buffer_pipe_buf_ops = { 7051static const struct pipe_buf_operations buffer_pipe_buf_ops = {
7053 .can_merge = 0,
7054 .confirm = generic_pipe_buf_confirm, 7052 .confirm = generic_pipe_buf_confirm,
7055 .release = buffer_pipe_buf_release, 7053 .release = buffer_pipe_buf_release,
7056 .steal = generic_pipe_buf_steal, 7054 .steal = generic_pipe_buf_steal,
diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c
index bbcf0fe4ae10..413a6abf227e 100644
--- a/net/smc/smc_rx.c
+++ b/net/smc/smc_rx.c
@@ -136,7 +136,6 @@ static int smc_rx_pipe_buf_nosteal(struct pipe_inode_info *pipe,
136} 136}
137 137
138static const struct pipe_buf_operations smc_pipe_ops = { 138static const struct pipe_buf_operations smc_pipe_ops = {
139 .can_merge = 0,
140 .confirm = generic_pipe_buf_confirm, 139 .confirm = generic_pipe_buf_confirm,
141 .release = smc_rx_pipe_buf_release, 140 .release = smc_rx_pipe_buf_release,
142 .steal = smc_rx_pipe_buf_nosteal, 141 .steal = smc_rx_pipe_buf_nosteal,