aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-23 12:22:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-23 12:22:58 -0500
commit5ee7a81a9fd9f663acdd7ecf6c395bcfc014b98f (patch)
treecba7e99f5c3a1026ca3594d6656bf04db090c553
parent0d90d638720ba14874e34cbd8766e4dc3f14f458 (diff)
parent7678ac50615d9c7a491d9861e020e4f5f71b594c (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse update from Miklos Szeredi: "This contains a fix for a potential use-after-module-unload bug noticed by Al and caching improvements for read-only fuse filesystems by Andrew Gallagher" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: fuse: support clients that don't implement 'open' fuse: don't invalidate attrs when not using atime fuse: fix SetPageUptodate() condition in STORE fuse: fix pipe_buf_operations
-rw-r--r--fs/fuse/dev.c25
-rw-r--r--fs/fuse/dir.c14
-rw-r--r--fs/fuse/file.c41
-rw-r--r--fs/fuse/fuse_i.h5
-rw-r--r--fs/splice.c18
-rw-r--r--include/linux/pipe_fs_i.h2
-rw-r--r--net/core/skbuff.c32
7 files changed, 74 insertions, 63 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index ef74ad5fd362..0a648bb455ae 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1296,22 +1296,6 @@ static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
1296 return fuse_dev_do_read(fc, file, &cs, iov_length(iov, nr_segs)); 1296 return fuse_dev_do_read(fc, file, &cs, iov_length(iov, nr_segs));
1297} 1297}
1298 1298
1299static int fuse_dev_pipe_buf_steal(struct pipe_inode_info *pipe,
1300 struct pipe_buffer *buf)
1301{
1302 return 1;
1303}
1304
1305static const struct pipe_buf_operations fuse_dev_pipe_buf_ops = {
1306 .can_merge = 0,
1307 .map = generic_pipe_buf_map,
1308 .unmap = generic_pipe_buf_unmap,
1309 .confirm = generic_pipe_buf_confirm,
1310 .release = generic_pipe_buf_release,
1311 .steal = fuse_dev_pipe_buf_steal,
1312 .get = generic_pipe_buf_get,
1313};
1314
1315static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos, 1299static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
1316 struct pipe_inode_info *pipe, 1300 struct pipe_inode_info *pipe,
1317 size_t len, unsigned int flags) 1301 size_t len, unsigned int flags)
@@ -1358,7 +1342,11 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
1358 buf->page = bufs[page_nr].page; 1342 buf->page = bufs[page_nr].page;
1359 buf->offset = bufs[page_nr].offset; 1343 buf->offset = bufs[page_nr].offset;
1360 buf->len = bufs[page_nr].len; 1344 buf->len = bufs[page_nr].len;
1361 buf->ops = &fuse_dev_pipe_buf_ops; 1345 /*
1346 * Need to be careful about this. Having buf->ops in module
1347 * code can Oops if the buffer persists after module unload.
1348 */
1349 buf->ops = &nosteal_pipe_buf_ops;
1362 1350
1363 pipe->nrbufs++; 1351 pipe->nrbufs++;
1364 page_nr++; 1352 page_nr++;
@@ -1599,7 +1587,8 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
1599 1587
1600 this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset); 1588 this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset);
1601 err = fuse_copy_page(cs, &page, offset, this_num, 0); 1589 err = fuse_copy_page(cs, &page, offset, this_num, 0);
1602 if (!err && offset == 0 && (num != 0 || file_size == end)) 1590 if (!err && offset == 0 &&
1591 (this_num == PAGE_CACHE_SIZE || file_size == end))
1603 SetPageUptodate(page); 1592 SetPageUptodate(page);
1604 unlock_page(page); 1593 unlock_page(page);
1605 page_cache_release(page); 1594 page_cache_release(page);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index c3eb2c46c8f1..1d1292c581c3 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -112,6 +112,16 @@ void fuse_invalidate_attr(struct inode *inode)
112 get_fuse_inode(inode)->i_time = 0; 112 get_fuse_inode(inode)->i_time = 0;
113} 113}
114 114
115/**
116 * Mark the attributes as stale due to an atime change. Avoid the invalidate if
117 * atime is not used.
118 */
119void fuse_invalidate_atime(struct inode *inode)
120{
121 if (!IS_RDONLY(inode))
122 fuse_invalidate_attr(inode);
123}
124
115/* 125/*
116 * Just mark the entry as stale, so that a next attempt to look it up 126 * Just mark the entry as stale, so that a next attempt to look it up
117 * will result in a new lookup call to userspace 127 * will result in a new lookup call to userspace
@@ -1371,7 +1381,7 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx)
1371 } 1381 }
1372 1382
1373 __free_page(page); 1383 __free_page(page);
1374 fuse_invalidate_attr(inode); /* atime changed */ 1384 fuse_invalidate_atime(inode);
1375 return err; 1385 return err;
1376} 1386}
1377 1387
@@ -1404,7 +1414,7 @@ static char *read_link(struct dentry *dentry)
1404 link[req->out.args[0].size] = '\0'; 1414 link[req->out.args[0].size] = '\0';
1405 out: 1415 out:
1406 fuse_put_request(fc, req); 1416 fuse_put_request(fc, req);
1407 fuse_invalidate_attr(inode); /* atime changed */ 1417 fuse_invalidate_atime(inode);
1408 return link; 1418 return link;
1409} 1419}
1410 1420
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 7e70506297bc..74f6ca500504 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -127,7 +127,15 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
127 if (atomic_dec_and_test(&ff->count)) { 127 if (atomic_dec_and_test(&ff->count)) {
128 struct fuse_req *req = ff->reserved_req; 128 struct fuse_req *req = ff->reserved_req;
129 129
130 if (sync) { 130 if (ff->fc->no_open) {
131 /*
132 * Drop the release request when client does not
133 * implement 'open'
134 */
135 req->background = 0;
136 path_put(&req->misc.release.path);
137 fuse_put_request(ff->fc, req);
138 } else if (sync) {
131 req->background = 0; 139 req->background = 0;
132 fuse_request_send(ff->fc, req); 140 fuse_request_send(ff->fc, req);
133 path_put(&req->misc.release.path); 141 path_put(&req->misc.release.path);
@@ -144,27 +152,36 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
144int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, 152int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
145 bool isdir) 153 bool isdir)
146{ 154{
147 struct fuse_open_out outarg;
148 struct fuse_file *ff; 155 struct fuse_file *ff;
149 int err;
150 int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; 156 int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
151 157
152 ff = fuse_file_alloc(fc); 158 ff = fuse_file_alloc(fc);
153 if (!ff) 159 if (!ff)
154 return -ENOMEM; 160 return -ENOMEM;
155 161
156 err = fuse_send_open(fc, nodeid, file, opcode, &outarg); 162 ff->fh = 0;
157 if (err) { 163 ff->open_flags = FOPEN_KEEP_CACHE; /* Default for no-open */
158 fuse_file_free(ff); 164 if (!fc->no_open || isdir) {
159 return err; 165 struct fuse_open_out outarg;
166 int err;
167
168 err = fuse_send_open(fc, nodeid, file, opcode, &outarg);
169 if (!err) {
170 ff->fh = outarg.fh;
171 ff->open_flags = outarg.open_flags;
172
173 } else if (err != -ENOSYS || isdir) {
174 fuse_file_free(ff);
175 return err;
176 } else {
177 fc->no_open = 1;
178 }
160 } 179 }
161 180
162 if (isdir) 181 if (isdir)
163 outarg.open_flags &= ~FOPEN_DIRECT_IO; 182 ff->open_flags &= ~FOPEN_DIRECT_IO;
164 183
165 ff->fh = outarg.fh;
166 ff->nodeid = nodeid; 184 ff->nodeid = nodeid;
167 ff->open_flags = outarg.open_flags;
168 file->private_data = fuse_file_get(ff); 185 file->private_data = fuse_file_get(ff);
169 186
170 return 0; 187 return 0;
@@ -687,7 +704,7 @@ static int fuse_readpage(struct file *file, struct page *page)
687 SetPageUptodate(page); 704 SetPageUptodate(page);
688 } 705 }
689 706
690 fuse_invalidate_attr(inode); /* atime changed */ 707 fuse_invalidate_atime(inode);
691 out: 708 out:
692 unlock_page(page); 709 unlock_page(page);
693 return err; 710 return err;
@@ -716,7 +733,7 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
716 fuse_read_update_size(inode, pos, 733 fuse_read_update_size(inode, pos,
717 req->misc.read.attr_ver); 734 req->misc.read.attr_ver);
718 } 735 }
719 fuse_invalidate_attr(inode); /* atime changed */ 736 fuse_invalidate_atime(inode);
720 } 737 }
721 738
722 for (i = 0; i < req->num_pages; i++) { 739 for (i = 0; i < req->num_pages; i++) {
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 7d2730912667..2da5db2c8bdb 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -485,6 +485,9 @@ struct fuse_conn {
485 * and hence races in setting them will not cause malfunction 485 * and hence races in setting them will not cause malfunction
486 */ 486 */
487 487
488 /** Is open/release not implemented by fs? */
489 unsigned no_open:1;
490
488 /** Is fsync not implemented by fs? */ 491 /** Is fsync not implemented by fs? */
489 unsigned no_fsync:1; 492 unsigned no_fsync:1;
490 493
@@ -788,6 +791,8 @@ void fuse_invalidate_attr(struct inode *inode);
788 791
789void fuse_invalidate_entry_cache(struct dentry *entry); 792void fuse_invalidate_entry_cache(struct dentry *entry);
790 793
794void fuse_invalidate_atime(struct inode *inode);
795
791/** 796/**
792 * Acquire reference to fuse_conn 797 * Acquire reference to fuse_conn
793 */ 798 */
diff --git a/fs/splice.c b/fs/splice.c
index 46a08f772d7d..12028fa41def 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -555,6 +555,24 @@ static const struct pipe_buf_operations default_pipe_buf_ops = {
555 .get = generic_pipe_buf_get, 555 .get = generic_pipe_buf_get,
556}; 556};
557 557
558static int generic_pipe_buf_nosteal(struct pipe_inode_info *pipe,
559 struct pipe_buffer *buf)
560{
561 return 1;
562}
563
564/* Pipe buffer operations for a socket and similar. */
565const struct pipe_buf_operations nosteal_pipe_buf_ops = {
566 .can_merge = 0,
567 .map = generic_pipe_buf_map,
568 .unmap = generic_pipe_buf_unmap,
569 .confirm = generic_pipe_buf_confirm,
570 .release = generic_pipe_buf_release,
571 .steal = generic_pipe_buf_nosteal,
572 .get = generic_pipe_buf_get,
573};
574EXPORT_SYMBOL(nosteal_pipe_buf_ops);
575
558static ssize_t kernel_readv(struct file *file, const struct iovec *vec, 576static ssize_t kernel_readv(struct file *file, const struct iovec *vec,
559 unsigned long vlen, loff_t offset) 577 unsigned long vlen, loff_t offset)
560{ 578{
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index b8809fef61f5..ab5752692113 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -157,6 +157,8 @@ int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *);
157int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *); 157int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
158void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *); 158void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *);
159 159
160extern const struct pipe_buf_operations nosteal_pipe_buf_ops;
161
160/* for F_SETPIPE_SZ and F_GETPIPE_SZ */ 162/* for F_SETPIPE_SZ and F_GETPIPE_SZ */
161long pipe_fcntl(struct file *, unsigned int, unsigned long arg); 163long pipe_fcntl(struct file *, unsigned int, unsigned long arg);
162struct pipe_inode_info *get_pipe_info(struct file *file); 164struct pipe_inode_info *get_pipe_info(struct file *file);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 06e72d3cdf60..0b5149c5bc4a 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -74,36 +74,6 @@
74struct kmem_cache *skbuff_head_cache __read_mostly; 74struct kmem_cache *skbuff_head_cache __read_mostly;
75static struct kmem_cache *skbuff_fclone_cache __read_mostly; 75static struct kmem_cache *skbuff_fclone_cache __read_mostly;
76 76
77static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
78 struct pipe_buffer *buf)
79{
80 put_page(buf->page);
81}
82
83static void sock_pipe_buf_get(struct pipe_inode_info *pipe,
84 struct pipe_buffer *buf)
85{
86 get_page(buf->page);
87}
88
89static int sock_pipe_buf_steal(struct pipe_inode_info *pipe,
90 struct pipe_buffer *buf)
91{
92 return 1;
93}
94
95
96/* Pipe buffer operations for a socket. */
97static const struct pipe_buf_operations sock_pipe_buf_ops = {
98 .can_merge = 0,
99 .map = generic_pipe_buf_map,
100 .unmap = generic_pipe_buf_unmap,
101 .confirm = generic_pipe_buf_confirm,
102 .release = sock_pipe_buf_release,
103 .steal = sock_pipe_buf_steal,
104 .get = sock_pipe_buf_get,
105};
106
107/** 77/**
108 * skb_panic - private function for out-of-line support 78 * skb_panic - private function for out-of-line support
109 * @skb: buffer 79 * @skb: buffer
@@ -1830,7 +1800,7 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
1830 .partial = partial, 1800 .partial = partial,
1831 .nr_pages_max = MAX_SKB_FRAGS, 1801 .nr_pages_max = MAX_SKB_FRAGS,
1832 .flags = flags, 1802 .flags = flags,
1833 .ops = &sock_pipe_buf_ops, 1803 .ops = &nosteal_pipe_buf_ops,
1834 .spd_release = sock_spd_release, 1804 .spd_release = sock_spd_release,
1835 }; 1805 };
1836 struct sk_buff *frag_iter; 1806 struct sk_buff *frag_iter;