aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-08-12 15:38:56 -0400
committerIngo Molnar <mingo@elte.hu>2010-08-12 15:39:04 -0400
commitf46a6804135795f77d096ab0128f27531c7d051c (patch)
tree7cd33f69e3661327739ae4c96e5a8389e7fc912e /fs/fuse
parentb3e84ffa21f916e3354a12a7f19169c9febe96d0 (diff)
parentad41a1e0cab07c5125456e8d38e5b1ab148d04aa (diff)
Merge branch 'linus' into perf/urgent
Merge reason: Fix upstream breakage introduced by: de5d9bf: Move list types from <linux/list.h> to <linux/types.h>. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dev.c229
-rw-r--r--fs/fuse/dir.c19
-rw-r--r--fs/fuse/file.c2
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--fs/fuse/inode.c6
5 files changed, 239 insertions, 20 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 9424796d6634..69ad053ffd78 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -239,7 +239,6 @@ static u64 fuse_get_unique(struct fuse_conn *fc)
239 239
240static void queue_request(struct fuse_conn *fc, struct fuse_req *req) 240static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
241{ 241{
242 req->in.h.unique = fuse_get_unique(fc);
243 req->in.h.len = sizeof(struct fuse_in_header) + 242 req->in.h.len = sizeof(struct fuse_in_header) +
244 len_args(req->in.numargs, (struct fuse_arg *) req->in.args); 243 len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
245 list_add_tail(&req->list, &fc->pending); 244 list_add_tail(&req->list, &fc->pending);
@@ -261,6 +260,7 @@ static void flush_bg_queue(struct fuse_conn *fc)
261 req = list_entry(fc->bg_queue.next, struct fuse_req, list); 260 req = list_entry(fc->bg_queue.next, struct fuse_req, list);
262 list_del(&req->list); 261 list_del(&req->list);
263 fc->active_background++; 262 fc->active_background++;
263 req->in.h.unique = fuse_get_unique(fc);
264 queue_request(fc, req); 264 queue_request(fc, req);
265 } 265 }
266} 266}
@@ -398,6 +398,7 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
398 else if (fc->conn_error) 398 else if (fc->conn_error)
399 req->out.h.error = -ECONNREFUSED; 399 req->out.h.error = -ECONNREFUSED;
400 else { 400 else {
401 req->in.h.unique = fuse_get_unique(fc);
401 queue_request(fc, req); 402 queue_request(fc, req);
402 /* acquire extra reference, since request is still needed 403 /* acquire extra reference, since request is still needed
403 after request_end() */ 404 after request_end() */
@@ -450,6 +451,23 @@ void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req)
450} 451}
451EXPORT_SYMBOL_GPL(fuse_request_send_background); 452EXPORT_SYMBOL_GPL(fuse_request_send_background);
452 453
454static int fuse_request_send_notify_reply(struct fuse_conn *fc,
455 struct fuse_req *req, u64 unique)
456{
457 int err = -ENODEV;
458
459 req->isreply = 0;
460 req->in.h.unique = unique;
461 spin_lock(&fc->lock);
462 if (fc->connected) {
463 queue_request(fc, req);
464 err = 0;
465 }
466 spin_unlock(&fc->lock);
467
468 return err;
469}
470
453/* 471/*
454 * Called under fc->lock 472 * Called under fc->lock
455 * 473 *
@@ -535,13 +553,13 @@ static void fuse_copy_finish(struct fuse_copy_state *cs)
535 if (!cs->write) { 553 if (!cs->write) {
536 buf->ops->unmap(cs->pipe, buf, cs->mapaddr); 554 buf->ops->unmap(cs->pipe, buf, cs->mapaddr);
537 } else { 555 } else {
538 kunmap_atomic(cs->mapaddr, KM_USER0); 556 kunmap(buf->page);
539 buf->len = PAGE_SIZE - cs->len; 557 buf->len = PAGE_SIZE - cs->len;
540 } 558 }
541 cs->currbuf = NULL; 559 cs->currbuf = NULL;
542 cs->mapaddr = NULL; 560 cs->mapaddr = NULL;
543 } else if (cs->mapaddr) { 561 } else if (cs->mapaddr) {
544 kunmap_atomic(cs->mapaddr, KM_USER0); 562 kunmap(cs->pg);
545 if (cs->write) { 563 if (cs->write) {
546 flush_dcache_page(cs->pg); 564 flush_dcache_page(cs->pg);
547 set_page_dirty_lock(cs->pg); 565 set_page_dirty_lock(cs->pg);
@@ -572,7 +590,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
572 590
573 BUG_ON(!cs->nr_segs); 591 BUG_ON(!cs->nr_segs);
574 cs->currbuf = buf; 592 cs->currbuf = buf;
575 cs->mapaddr = buf->ops->map(cs->pipe, buf, 1); 593 cs->mapaddr = buf->ops->map(cs->pipe, buf, 0);
576 cs->len = buf->len; 594 cs->len = buf->len;
577 cs->buf = cs->mapaddr + buf->offset; 595 cs->buf = cs->mapaddr + buf->offset;
578 cs->pipebufs++; 596 cs->pipebufs++;
@@ -592,7 +610,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
592 buf->len = 0; 610 buf->len = 0;
593 611
594 cs->currbuf = buf; 612 cs->currbuf = buf;
595 cs->mapaddr = kmap_atomic(page, KM_USER0); 613 cs->mapaddr = kmap(page);
596 cs->buf = cs->mapaddr; 614 cs->buf = cs->mapaddr;
597 cs->len = PAGE_SIZE; 615 cs->len = PAGE_SIZE;
598 cs->pipebufs++; 616 cs->pipebufs++;
@@ -611,7 +629,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
611 return err; 629 return err;
612 BUG_ON(err != 1); 630 BUG_ON(err != 1);
613 offset = cs->addr % PAGE_SIZE; 631 offset = cs->addr % PAGE_SIZE;
614 cs->mapaddr = kmap_atomic(cs->pg, KM_USER0); 632 cs->mapaddr = kmap(cs->pg);
615 cs->buf = cs->mapaddr + offset; 633 cs->buf = cs->mapaddr + offset;
616 cs->len = min(PAGE_SIZE - offset, cs->seglen); 634 cs->len = min(PAGE_SIZE - offset, cs->seglen);
617 cs->seglen -= cs->len; 635 cs->seglen -= cs->len;
@@ -1231,6 +1249,199 @@ err:
1231 return err; 1249 return err;
1232} 1250}
1233 1251
1252static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
1253 struct fuse_copy_state *cs)
1254{
1255 struct fuse_notify_store_out outarg;
1256 struct inode *inode;
1257 struct address_space *mapping;
1258 u64 nodeid;
1259 int err;
1260 pgoff_t index;
1261 unsigned int offset;
1262 unsigned int num;
1263 loff_t file_size;
1264 loff_t end;
1265
1266 err = -EINVAL;
1267 if (size < sizeof(outarg))
1268 goto out_finish;
1269
1270 err = fuse_copy_one(cs, &outarg, sizeof(outarg));
1271 if (err)
1272 goto out_finish;
1273
1274 err = -EINVAL;
1275 if (size - sizeof(outarg) != outarg.size)
1276 goto out_finish;
1277
1278 nodeid = outarg.nodeid;
1279
1280 down_read(&fc->killsb);
1281
1282 err = -ENOENT;
1283 if (!fc->sb)
1284 goto out_up_killsb;
1285
1286 inode = ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid);
1287 if (!inode)
1288 goto out_up_killsb;
1289
1290 mapping = inode->i_mapping;
1291 index = outarg.offset >> PAGE_CACHE_SHIFT;
1292 offset = outarg.offset & ~PAGE_CACHE_MASK;
1293 file_size = i_size_read(inode);
1294 end = outarg.offset + outarg.size;
1295 if (end > file_size) {
1296 file_size = end;
1297 fuse_write_update_size(inode, file_size);
1298 }
1299
1300 num = outarg.size;
1301 while (num) {
1302 struct page *page;
1303 unsigned int this_num;
1304
1305 err = -ENOMEM;
1306 page = find_or_create_page(mapping, index,
1307 mapping_gfp_mask(mapping));
1308 if (!page)
1309 goto out_iput;
1310
1311 this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset);
1312 err = fuse_copy_page(cs, &page, offset, this_num, 0);
1313 if (!err && offset == 0 && (num != 0 || file_size == end))
1314 SetPageUptodate(page);
1315 unlock_page(page);
1316 page_cache_release(page);
1317
1318 if (err)
1319 goto out_iput;
1320
1321 num -= this_num;
1322 offset = 0;
1323 index++;
1324 }
1325
1326 err = 0;
1327
1328out_iput:
1329 iput(inode);
1330out_up_killsb:
1331 up_read(&fc->killsb);
1332out_finish:
1333 fuse_copy_finish(cs);
1334 return err;
1335}
1336
1337static void fuse_retrieve_end(struct fuse_conn *fc, struct fuse_req *req)
1338{
1339 int i;
1340
1341 for (i = 0; i < req->num_pages; i++) {
1342 struct page *page = req->pages[i];
1343 page_cache_release(page);
1344 }
1345}
1346
1347static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
1348 struct fuse_notify_retrieve_out *outarg)
1349{
1350 int err;
1351 struct address_space *mapping = inode->i_mapping;
1352 struct fuse_req *req;
1353 pgoff_t index;
1354 loff_t file_size;
1355 unsigned int num;
1356 unsigned int offset;
1357 size_t total_len;
1358
1359 req = fuse_get_req(fc);
1360 if (IS_ERR(req))
1361 return PTR_ERR(req);
1362
1363 offset = outarg->offset & ~PAGE_CACHE_MASK;
1364
1365 req->in.h.opcode = FUSE_NOTIFY_REPLY;
1366 req->in.h.nodeid = outarg->nodeid;
1367 req->in.numargs = 2;
1368 req->in.argpages = 1;
1369 req->page_offset = offset;
1370 req->end = fuse_retrieve_end;
1371
1372 index = outarg->offset >> PAGE_CACHE_SHIFT;
1373 file_size = i_size_read(inode);
1374 num = outarg->size;
1375 if (outarg->offset > file_size)
1376 num = 0;
1377 else if (outarg->offset + num > file_size)
1378 num = file_size - outarg->offset;
1379
1380 while (num) {
1381 struct page *page;
1382 unsigned int this_num;
1383
1384 page = find_get_page(mapping, index);
1385 if (!page)
1386 break;
1387
1388 this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset);
1389 req->pages[req->num_pages] = page;
1390 req->num_pages++;
1391
1392 num -= this_num;
1393 total_len += this_num;
1394 }
1395 req->misc.retrieve_in.offset = outarg->offset;
1396 req->misc.retrieve_in.size = total_len;
1397 req->in.args[0].size = sizeof(req->misc.retrieve_in);
1398 req->in.args[0].value = &req->misc.retrieve_in;
1399 req->in.args[1].size = total_len;
1400
1401 err = fuse_request_send_notify_reply(fc, req, outarg->notify_unique);
1402 if (err)
1403 fuse_retrieve_end(fc, req);
1404
1405 return err;
1406}
1407
1408static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size,
1409 struct fuse_copy_state *cs)
1410{
1411 struct fuse_notify_retrieve_out outarg;
1412 struct inode *inode;
1413 int err;
1414
1415 err = -EINVAL;
1416 if (size != sizeof(outarg))
1417 goto copy_finish;
1418
1419 err = fuse_copy_one(cs, &outarg, sizeof(outarg));
1420 if (err)
1421 goto copy_finish;
1422
1423 fuse_copy_finish(cs);
1424
1425 down_read(&fc->killsb);
1426 err = -ENOENT;
1427 if (fc->sb) {
1428 u64 nodeid = outarg.nodeid;
1429
1430 inode = ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid);
1431 if (inode) {
1432 err = fuse_retrieve(fc, inode, &outarg);
1433 iput(inode);
1434 }
1435 }
1436 up_read(&fc->killsb);
1437
1438 return err;
1439
1440copy_finish:
1441 fuse_copy_finish(cs);
1442 return err;
1443}
1444
1234static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, 1445static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
1235 unsigned int size, struct fuse_copy_state *cs) 1446 unsigned int size, struct fuse_copy_state *cs)
1236{ 1447{
@@ -1244,6 +1455,12 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
1244 case FUSE_NOTIFY_INVAL_ENTRY: 1455 case FUSE_NOTIFY_INVAL_ENTRY:
1245 return fuse_notify_inval_entry(fc, size, cs); 1456 return fuse_notify_inval_entry(fc, size, cs);
1246 1457
1458 case FUSE_NOTIFY_STORE:
1459 return fuse_notify_store(fc, size, cs);
1460
1461 case FUSE_NOTIFY_RETRIEVE:
1462 return fuse_notify_retrieve(fc, size, cs);
1463
1247 default: 1464 default:
1248 fuse_copy_finish(cs); 1465 fuse_copy_finish(cs);
1249 return -EINVAL; 1466 return -EINVAL;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 3cdc5f78a406..c9627c95482d 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1016,7 +1016,7 @@ static int fuse_permission(struct inode *inode, int mask)
1016 exist. So if permissions are revoked this won't be 1016 exist. So if permissions are revoked this won't be
1017 noticed immediately, only after the attribute 1017 noticed immediately, only after the attribute
1018 timeout has expired */ 1018 timeout has expired */
1019 } else if (mask & MAY_ACCESS) { 1019 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1020 err = fuse_access(inode, mask); 1020 err = fuse_access(inode, mask);
1021 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1021 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1022 if (!(inode->i_mode & S_IXUGO)) { 1022 if (!(inode->i_mode & S_IXUGO)) {
@@ -1270,21 +1270,18 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
1270 if (!fuse_allow_task(fc, current)) 1270 if (!fuse_allow_task(fc, current))
1271 return -EACCES; 1271 return -EACCES;
1272 1272
1273 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 1273 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1274 err = inode_change_ok(inode, attr); 1274 attr->ia_valid |= ATTR_FORCE;
1275 if (err) 1275
1276 return err; 1276 err = inode_change_ok(inode, attr);
1277 } 1277 if (err)
1278 return err;
1278 1279
1279 if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc) 1280 if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc)
1280 return 0; 1281 return 0;
1281 1282
1282 if (attr->ia_valid & ATTR_SIZE) { 1283 if (attr->ia_valid & ATTR_SIZE)
1283 err = inode_newsize_ok(inode, attr->ia_size);
1284 if (err)
1285 return err;
1286 is_truncate = true; 1284 is_truncate = true;
1287 }
1288 1285
1289 req = fuse_get_req(fc); 1286 req = fuse_get_req(fc);
1290 if (IS_ERR(req)) 1287 if (IS_ERR(req))
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index ada0adeb3bb5..147c1f71bdb9 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -706,7 +706,7 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping,
706 return 0; 706 return 0;
707} 707}
708 708
709static void fuse_write_update_size(struct inode *inode, loff_t pos) 709void fuse_write_update_size(struct inode *inode, loff_t pos)
710{ 710{
711 struct fuse_conn *fc = get_fuse_conn(inode); 711 struct fuse_conn *fc = get_fuse_conn(inode);
712 struct fuse_inode *fi = get_fuse_inode(inode); 712 struct fuse_inode *fi = get_fuse_inode(inode);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 8f309f04064e..57d4a3a0f102 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -272,6 +272,7 @@ struct fuse_req {
272 struct fuse_write_in in; 272 struct fuse_write_in in;
273 struct fuse_write_out out; 273 struct fuse_write_out out;
274 } write; 274 } write;
275 struct fuse_notify_retrieve_in retrieve_in;
275 struct fuse_lk_in lk_in; 276 struct fuse_lk_in lk_in;
276 } misc; 277 } misc;
277 278
@@ -748,4 +749,6 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
748unsigned fuse_file_poll(struct file *file, poll_table *wait); 749unsigned fuse_file_poll(struct file *file, poll_table *wait);
749int fuse_dev_release(struct inode *inode, struct file *file); 750int fuse_dev_release(struct inode *inode, struct file *file);
750 751
752void fuse_write_update_size(struct inode *inode, loff_t pos);
753
751#endif /* _FS_FUSE_I_H */ 754#endif /* _FS_FUSE_I_H */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index ec14d19ce501..da9e6e11374c 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -122,8 +122,10 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
122 fuse_request_send_noreply(fc, req); 122 fuse_request_send_noreply(fc, req);
123} 123}
124 124
125static void fuse_clear_inode(struct inode *inode) 125static void fuse_evict_inode(struct inode *inode)
126{ 126{
127 truncate_inode_pages(&inode->i_data, 0);
128 end_writeback(inode);
127 if (inode->i_sb->s_flags & MS_ACTIVE) { 129 if (inode->i_sb->s_flags & MS_ACTIVE) {
128 struct fuse_conn *fc = get_fuse_conn(inode); 130 struct fuse_conn *fc = get_fuse_conn(inode);
129 struct fuse_inode *fi = get_fuse_inode(inode); 131 struct fuse_inode *fi = get_fuse_inode(inode);
@@ -736,7 +738,7 @@ static const struct export_operations fuse_export_operations = {
736static const struct super_operations fuse_super_operations = { 738static const struct super_operations fuse_super_operations = {
737 .alloc_inode = fuse_alloc_inode, 739 .alloc_inode = fuse_alloc_inode,
738 .destroy_inode = fuse_destroy_inode, 740 .destroy_inode = fuse_destroy_inode,
739 .clear_inode = fuse_clear_inode, 741 .evict_inode = fuse_evict_inode,
740 .drop_inode = generic_delete_inode, 742 .drop_inode = generic_delete_inode,
741 .remount_fs = fuse_remount_fs, 743 .remount_fs = fuse_remount_fs,
742 .put_super = fuse_put_super, 744 .put_super = fuse_put_super,