Unified · Split
| @@ -1308,12 +1308,17 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) · 1307 unmodified lines | ||
| 1308 | 1308 | struct inode *inode = file_inode(vma->vm_file); |
| 1309 | 1309 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 1310 | 1310 | struct ceph_file_info *fi = vma->vm_file->private_data; |
| 1311 | + struct ceph_cap_flush *prealloc_cf; | |
| 1311 | 1312 | struct page *page = vmf->page; |
| 1312 | 1313 | loff_t off = page_offset(page); |
| 1313 | 1314 | loff_t size = i_size_read(inode); |
| 1314 | 1315 | size_t len; |
| 1315 | 1316 | int want, got, ret; |
| 1316 | 1317 | |
| 1318 | + prealloc_cf = ceph_alloc_cap_flush(); | |
| 1319 | + if (!prealloc_cf) | |
| 1320 | + return VM_FAULT_SIGBUS; | |
| 1321 | + | |
| 1317 | 1322 | if (ci->i_inline_version != CEPH_INLINE_NONE) { |
| 1318 | 1323 | struct page *locked_page = NULL; |
| 1319 | 1324 | if (off == 0) { |
| @@ -1323,8 +1328,10 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) · 3 unmodified lines | ||
| 1323 | 1328 | ret = ceph_uninline_data(vma->vm_file, locked_page); |
| 1324 | 1329 | if (locked_page) |
| 1325 | 1330 | unlock_page(locked_page); |
| 1326 | − if (ret < 0) | |
| 1327 | − return VM_FAULT_SIGBUS; | |
| 1331 | + if (ret < 0) { | |
| 1332 | + ret = VM_FAULT_SIGBUS; | |
| 1333 | + goto out_free; | |
| 1334 | + } | |
| 1328 | 1335 | } |
| 1329 | 1336 | |
| 1330 | 1337 | if (off + PAGE_CACHE_SIZE <= size) |
| @@ -1346,7 +1353,8 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) · 15 unmodified lines | ||
| 1346 | 1353 | break; |
| 1347 | 1354 | if (ret != -ERESTARTSYS) { |
| 1348 | 1355 | WARN_ON(1); |
| 1349 | − return VM_FAULT_SIGBUS; | |
| 1356 | + ret = VM_FAULT_SIGBUS; | |
| 1357 | + goto out_free; | |
| 1350 | 1358 | } |
| 1351 | 1359 | } |
| 1352 | 1360 | dout("page_mkwrite %p %llu~%zd got cap refs on %s\n", |
| @@ -1381,7 +1389,8 @@ out: · 28 unmodified lines | ||
| 1381 | 1389 | int dirty; |
| 1382 | 1390 | spin_lock(&ci->i_ceph_lock); |
| 1383 | 1391 | ci->i_inline_version = CEPH_INLINE_NONE; |
| 1384 | − dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); | |
| 1392 | + dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR, | |
| 1393 | + &prealloc_cf); | |
| 1385 | 1394 | spin_unlock(&ci->i_ceph_lock); |
| 1386 | 1395 | if (dirty) |
| 1387 | 1396 | __mark_inode_dirty(inode, dirty); |
| @@ -1390,6 +1399,8 @@ out: · 2 unmodified lines | ||
| 1390 | 1399 | dout("page_mkwrite %p %llu~%zd dropping cap refs on %s ret %d\n", |
| 1391 | 1400 | inode, off, len, ceph_cap_string(got), ret); |
| 1392 | 1401 | ceph_put_cap_refs(ci, got); |
| 1402 | +out_free: | |
| 1403 | + ceph_free_cap_flush(prealloc_cf); | |
| 1393 | 1404 | |
| 1394 | 1405 | return ret; |
| 1395 | 1406 | } |
| @@ -1356,7 +1356,8 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci) · 1355 unmodified lines | ||
| 1356 | 1356 | * Caller is then responsible for calling __mark_inode_dirty with the |
| 1357 | 1357 | * returned flags value. |
| 1358 | 1358 | */ |
| 1359 | −int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) | |
| 1359 | +int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask, | |
| 1360 | + struct ceph_cap_flush **pcf) | |
| 1360 | 1361 | { |
| 1361 | 1362 | struct ceph_mds_client *mdsc = |
| 1362 | 1363 | ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; |
| @@ -1376,6 +1377,9 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) · 13 unmodified lines | ||
| 1376 | 1377 | ceph_cap_string(was | mask)); |
| 1377 | 1378 | ci->i_dirty_caps |= mask; |
| 1378 | 1379 | if (was == 0) { |
| 1380 | + WARN_ON_ONCE(ci->i_prealloc_cap_flush); | |
| 1381 | + swap(ci->i_prealloc_cap_flush, *pcf); | |
| 1382 | + | |
| 1379 | 1383 | if (!ci->i_head_snapc) { |
| 1380 | 1384 | WARN_ON_ONCE(!rwsem_is_locked(&mdsc->snap_rwsem)); |
| 1381 | 1385 | ci->i_head_snapc = ceph_get_snap_context( |
| @@ -1391,6 +1395,8 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) · 9 unmodified lines | ||
| 1391 | 1395 | ihold(inode); |
| 1392 | 1396 | dirty |= I_DIRTY_SYNC; |
| 1393 | 1397 | } |
| 1398 | + } else { | |
| 1399 | + WARN_ON_ONCE(!ci->i_prealloc_cap_flush); | |
| 1394 | 1400 | } |
| 1395 | 1401 | BUG_ON(list_empty(&ci->i_dirty_item)); |
| 1396 | 1402 | if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) && |
| @@ -1446,6 +1452,17 @@ static void __add_cap_flushing_to_mdsc(struct ceph_mds_client *mdsc, · 49 unmodified lines | ||
| 1446 | 1452 | rb_insert_color(&cf->g_node, &mdsc->cap_flush_tree); |
| 1447 | 1453 | } |
| 1448 | 1454 | |
| 1455 | +struct ceph_cap_flush *ceph_alloc_cap_flush(void) | |
| 1456 | +{ | |
| 1457 | + return kmem_cache_alloc(ceph_cap_flush_cachep, GFP_KERNEL); | |
| 1458 | +} | |
| 1459 | + | |
| 1460 | +void ceph_free_cap_flush(struct ceph_cap_flush *cf) | |
| 1461 | +{ | |
| 1462 | + if (cf) | |
| 1463 | + kmem_cache_free(ceph_cap_flush_cachep, cf); | |
| 1464 | +} | |
| 1465 | + | |
| 1449 | 1466 | static u64 __get_oldest_flush_tid(struct ceph_mds_client *mdsc) |
| 1450 | 1467 | { |
| 1451 | 1468 | struct rb_node *n = rb_first(&mdsc->cap_flush_tree); |
| @@ -1469,11 +1486,12 @@ static int __mark_caps_flushing(struct inode *inode, · 17 unmodified lines | ||
| 1469 | 1486 | { |
| 1470 | 1487 | struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; |
| 1471 | 1488 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 1472 | − struct ceph_cap_flush *cf; | |
| 1489 | + struct ceph_cap_flush *cf = NULL; | |
| 1473 | 1490 | int flushing; |
| 1474 | 1491 | |
| 1475 | 1492 | BUG_ON(ci->i_dirty_caps == 0); |
| 1476 | 1493 | BUG_ON(list_empty(&ci->i_dirty_item)); |
| 1494 | + BUG_ON(!ci->i_prealloc_cap_flush); | |
| 1477 | 1495 | |
| 1478 | 1496 | flushing = ci->i_dirty_caps; |
| 1479 | 1497 | dout("__mark_caps_flushing flushing %s, flushing_caps %s -> %s\n", |
| @@ -1484,7 +1502,7 @@ static int __mark_caps_flushing(struct inode *inode, · 4 unmodified lines | ||
| 1484 | 1502 | ci->i_dirty_caps = 0; |
| 1485 | 1503 | dout(" inode %p now !dirty\n", inode); |
| 1486 | 1504 | |
| 1487 | − cf = kmalloc(sizeof(*cf), GFP_ATOMIC); | |
| 1505 | + swap(cf, ci->i_prealloc_cap_flush); | |
| 1488 | 1506 | cf->caps = flushing; |
| 1489 | 1507 | cf->kick = false; |
| 1490 | 1508 | |
| @@ -3075,7 +3093,7 @@ out: · 1584 unmodified lines | ||
| 3075 | 3093 | cf = list_first_entry(&to_remove, |
| 3076 | 3094 | struct ceph_cap_flush, list); |
| 3077 | 3095 | list_del(&cf->list); |
| 3078 | − kfree(cf); | |
| 3096 | + ceph_free_cap_flush(cf); | |
| 3079 | 3097 | } |
| 3080 | 3098 | if (drop) |
| 3081 | 3099 | iput(inode); |
| @@ -939,6 +939,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from) · 938 unmodified lines | ||
| 939 | 939 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 940 | 940 | struct ceph_osd_client *osdc = |
| 941 | 941 | &ceph_sb_to_client(inode->i_sb)->client->osdc; |
| 942 | + struct ceph_cap_flush *prealloc_cf; | |
| 942 | 943 | ssize_t count, written = 0; |
| 943 | 944 | int err, want, got; |
| 944 | 945 | loff_t pos; |
| @@ -946,6 +947,10 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from) · 1 unmodified line | ||
| 946 | 947 | if (ceph_snap(inode) != CEPH_NOSNAP) |
| 947 | 948 | return -EROFS; |
| 948 | 949 | |
| 950 | + prealloc_cf = ceph_alloc_cap_flush(); | |
| 951 | + if (!prealloc_cf) | |
| 952 | + return -ENOMEM; | |
| 953 | + | |
| 949 | 954 | mutex_lock(&inode->i_mutex); |
| 950 | 955 | |
| 951 | 956 | /* We can write back this queue in page reclaim */ |
| @@ -1050,7 +1055,8 @@ retry_snap: · 98 unmodified lines | ||
| 1050 | 1055 | int dirty; |
| 1051 | 1056 | spin_lock(&ci->i_ceph_lock); |
| 1052 | 1057 | ci->i_inline_version = CEPH_INLINE_NONE; |
| 1053 | − dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); | |
| 1058 | + dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR, | |
| 1059 | + &prealloc_cf); | |
| 1054 | 1060 | spin_unlock(&ci->i_ceph_lock); |
| 1055 | 1061 | if (dirty) |
| 1056 | 1062 | __mark_inode_dirty(inode, dirty); |
| @@ -1074,6 +1080,7 @@ retry_snap: · 17 unmodified lines | ||
| 1074 | 1080 | out: |
| 1075 | 1081 | mutex_unlock(&inode->i_mutex); |
| 1076 | 1082 | out_unlocked: |
| 1083 | + ceph_free_cap_flush(prealloc_cf); | |
| 1077 | 1084 | current->backing_dev_info = NULL; |
| 1078 | 1085 | return written ? written : err; |
| 1079 | 1086 | } |
| @@ -1270,6 +1277,7 @@ static long ceph_fallocate(struct file *file, int mode, · 190 unmodified lines | ||
| 1270 | 1277 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 1271 | 1278 | struct ceph_osd_client *osdc = |
| 1272 | 1279 | &ceph_inode_to_client(inode)->client->osdc; |
| 1280 | + struct ceph_cap_flush *prealloc_cf; | |
| 1273 | 1281 | int want, got = 0; |
| 1274 | 1282 | int dirty; |
| 1275 | 1283 | int ret = 0; |
| @@ -1282,6 +1290,10 @@ static long ceph_fallocate(struct file *file, int mode, · 6 unmodified lines | ||
| 1282 | 1290 | if (!S_ISREG(inode->i_mode)) |
| 1283 | 1291 | return -EOPNOTSUPP; |
| 1284 | 1292 | |
| 1293 | + prealloc_cf = ceph_alloc_cap_flush(); | |
| 1294 | + if (!prealloc_cf) | |
| 1295 | + return -ENOMEM; | |
| 1296 | + | |
| 1285 | 1297 | mutex_lock(&inode->i_mutex); |
| 1286 | 1298 | |
| 1287 | 1299 | if (ceph_snap(inode) != CEPH_NOSNAP) { |
| @@ -1328,7 +1340,8 @@ static long ceph_fallocate(struct file *file, int mode, · 40 unmodified lines | ||
| 1328 | 1340 | if (!ret) { |
| 1329 | 1341 | spin_lock(&ci->i_ceph_lock); |
| 1330 | 1342 | ci->i_inline_version = CEPH_INLINE_NONE; |
| 1331 | − dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); | |
| 1343 | + dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR, | |
| 1344 | + &prealloc_cf); | |
| 1332 | 1345 | spin_unlock(&ci->i_ceph_lock); |
| 1333 | 1346 | if (dirty) |
| 1334 | 1347 | __mark_inode_dirty(inode, dirty); |
| @@ -1337,6 +1350,7 @@ static long ceph_fallocate(struct file *file, int mode, · 2 unmodified lines | ||
| 1337 | 1350 | ceph_put_cap_refs(ci, got); |
| 1338 | 1351 | unlock: |
| 1339 | 1352 | mutex_unlock(&inode->i_mutex); |
| 1353 | + ceph_free_cap_flush(prealloc_cf); | |
| 1340 | 1354 | return ret; |
| 1341 | 1355 | } |
| 1342 | 1356 | |
| @@ -416,6 +416,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb) · 415 unmodified lines | ||
| 416 | 416 | ci->i_flushing_caps = 0; |
| 417 | 417 | INIT_LIST_HEAD(&ci->i_dirty_item); |
| 418 | 418 | INIT_LIST_HEAD(&ci->i_flushing_item); |
| 419 | + ci->i_prealloc_cap_flush = NULL; | |
| 419 | 420 | ci->i_cap_flush_tree = RB_ROOT; |
| 420 | 421 | init_waitqueue_head(&ci->i_cap_wq); |
| 421 | 422 | ci->i_hold_caps_min = 0; |
| @@ -1720,6 +1721,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) · 1298 unmodified lines | ||
| 1720 | 1721 | const unsigned int ia_valid = attr->ia_valid; |
| 1721 | 1722 | struct ceph_mds_request *req; |
| 1722 | 1723 | struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc; |
| 1724 | + struct ceph_cap_flush *prealloc_cf; | |
| 1723 | 1725 | int issued; |
| 1724 | 1726 | int release = 0, dirtied = 0; |
| 1725 | 1727 | int mask = 0; |
| @@ -1734,10 +1736,16 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) · 8 unmodified lines | ||
| 1734 | 1736 | if (err != 0) |
| 1735 | 1737 | return err; |
| 1736 | 1738 | |
| 1739 | + prealloc_cf = ceph_alloc_cap_flush(); | |
| 1740 | + if (!prealloc_cf) | |
| 1741 | + return -ENOMEM; | |
| 1742 | + | |
| 1737 | 1743 | req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETATTR, |
| 1738 | 1744 | USE_AUTH_MDS); |
| 1739 | − if (IS_ERR(req)) | |
| 1745 | + if (IS_ERR(req)) { | |
| 1746 | + ceph_free_cap_flush(prealloc_cf); | |
| 1740 | 1747 | return PTR_ERR(req); |
| 1748 | + } | |
| 1741 | 1749 | |
| 1742 | 1750 | spin_lock(&ci->i_ceph_lock); |
| 1743 | 1751 | issued = __ceph_caps_issued(ci, NULL); |
| @@ -1895,7 +1903,8 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) · 151 unmodified lines | ||
| 1895 | 1903 | dout("setattr %p ATTR_FILE ... hrm!\n", inode); |
| 1896 | 1904 | |
| 1897 | 1905 | if (dirtied) { |
| 1898 | − inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied); | |
| 1906 | + inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied, | |
| 1907 | + &prealloc_cf); | |
| 1899 | 1908 | inode->i_ctime = CURRENT_TIME; |
| 1900 | 1909 | } |
| 1901 | 1910 | |
| @@ -1927,9 +1936,11 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) · 25 unmodified lines | ||
| 1927 | 1936 | ceph_mdsc_put_request(req); |
| 1928 | 1937 | if (mask & CEPH_SETATTR_SIZE) |
| 1929 | 1938 | __ceph_do_pending_vmtruncate(inode); |
| 1939 | + ceph_free_cap_flush(prealloc_cf); | |
| 1930 | 1940 | return err; |
| 1931 | 1941 | out_put: |
| 1932 | 1942 | ceph_mdsc_put_request(req); |
| 1943 | + ceph_free_cap_flush(prealloc_cf); | |
| 1933 | 1944 | return err; |
| 1934 | 1945 | } |
| 1935 | 1946 | |
| @@ -1189,6 +1189,10 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, · 1188 unmodified lines | ||
| 1189 | 1189 | } |
| 1190 | 1190 | spin_unlock(&mdsc->cap_dirty_lock); |
| 1191 | 1191 | |
| 1192 | + if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) { | |
| 1193 | + list_add(&ci->i_prealloc_cap_flush->list, &to_remove); | |
| 1194 | + ci->i_prealloc_cap_flush = NULL; | |
| 1195 | + } | |
| 1192 | 1196 | } |
| 1193 | 1197 | spin_unlock(&ci->i_ceph_lock); |
| 1194 | 1198 | while (!list_empty(&to_remove)) { |
| @@ -1196,7 +1200,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, · 1 unmodified line | ||
| 1196 | 1200 | cf = list_first_entry(&to_remove, |
| 1197 | 1201 | struct ceph_cap_flush, list); |
| 1198 | 1202 | list_del(&cf->list); |
| 1199 | − kfree(cf); | |
| 1203 | + ceph_free_cap_flush(cf); | |
| 1200 | 1204 | } |
| 1201 | 1205 | while (drop--) |
| 1202 | 1206 | iput(inode); |
| @@ -622,6 +622,7 @@ static void destroy_fs_client(struct ceph_fs_client *fsc) · 621 unmodified lines | ||
| 622 | 622 | */ |
| 623 | 623 | struct kmem_cache *ceph_inode_cachep; |
| 624 | 624 | struct kmem_cache *ceph_cap_cachep; |
| 625 | +struct kmem_cache *ceph_cap_flush_cachep; | |
| 625 | 626 | struct kmem_cache *ceph_dentry_cachep; |
| 626 | 627 | struct kmem_cache *ceph_file_cachep; |
| 627 | 628 | |
| @@ -647,6 +648,10 @@ static int __init init_caches(void) · 19 unmodified lines | ||
| 647 | 648 | SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD); |
| 648 | 649 | if (ceph_cap_cachep == NULL) |
| 649 | 650 | goto bad_cap; |
| 651 | + ceph_cap_flush_cachep = KMEM_CACHE(ceph_cap_flush, | |
| 652 | + SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD); | |
| 653 | + if (ceph_cap_flush_cachep == NULL) | |
| 654 | + goto bad_cap_flush; | |
| 650 | 655 | |
| 651 | 656 | ceph_dentry_cachep = KMEM_CACHE(ceph_dentry_info, |
| 652 | 657 | SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD); |
| @@ -665,6 +670,8 @@ static int __init init_caches(void) · 12 unmodified lines | ||
| 665 | 670 | bad_file: |
| 666 | 671 | kmem_cache_destroy(ceph_dentry_cachep); |
| 667 | 672 | bad_dentry: |
| 673 | + kmem_cache_destroy(ceph_cap_flush_cachep); | |
| 674 | +bad_cap_flush: | |
| 668 | 675 | kmem_cache_destroy(ceph_cap_cachep); |
| 669 | 676 | bad_cap: |
| 670 | 677 | kmem_cache_destroy(ceph_inode_cachep); |
| @@ -681,6 +688,7 @@ static void destroy_caches(void) · 10 unmodified lines | ||
| 681 | 688 | |
| 682 | 689 | kmem_cache_destroy(ceph_inode_cachep); |
| 683 | 690 | kmem_cache_destroy(ceph_cap_cachep); |
| 691 | + kmem_cache_destroy(ceph_cap_flush_cachep); | |
| 684 | 692 | kmem_cache_destroy(ceph_dentry_cachep); |
| 685 | 693 | kmem_cache_destroy(ceph_file_cachep); |
| 686 | 694 | |
| @@ -309,6 +309,7 @@ struct ceph_inode_info { · 308 unmodified lines | ||
| 309 | 309 | /* we need to track cap writeback on a per-cap-bit basis, to allow |
| 310 | 310 | * overlapping, pipelined cap flushes to the mds. we can probably |
| 311 | 311 | * reduce the tid to 8 bits if we're concerned about inode size. */ |
| 312 | + struct ceph_cap_flush *i_prealloc_cap_flush; | |
| 312 | 313 | struct rb_root i_cap_flush_tree; |
| 313 | 314 | wait_queue_head_t i_cap_wq; /* threads waiting on a capability */ |
| 314 | 315 | unsigned long i_hold_caps_min; /* jiffies */ |
| @@ -578,7 +579,10 @@ static inline int __ceph_caps_dirty(struct ceph_inode_info *ci) · 263 unmodified lines | ||
| 578 | 579 | { |
| 579 | 580 | return ci->i_dirty_caps | ci->i_flushing_caps; |
| 580 | 581 | } |
| 581 | −extern int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask); | |
| 582 | +extern struct ceph_cap_flush *ceph_alloc_cap_flush(void); | |
| 583 | +extern void ceph_free_cap_flush(struct ceph_cap_flush *cf); | |
| 584 | +extern int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask, | |
| 585 | + struct ceph_cap_flush **pcf); | |
| 582 | 586 | |
| 583 | 587 | extern int __ceph_caps_revoking_other(struct ceph_inode_info *ci, |
| 584 | 588 | struct ceph_cap *ocap, int mask); |
| @@ -912,6 +912,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name, · 911 unmodified lines | ||
| 912 | 912 | struct ceph_vxattr *vxattr; |
| 913 | 913 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 914 | 914 | struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc; |
| 915 | + struct ceph_cap_flush *prealloc_cf = NULL; | |
| 915 | 916 | int issued; |
| 916 | 917 | int err; |
| 917 | 918 | int dirty = 0; |
| @@ -950,6 +951,10 @@ int __ceph_setxattr(struct dentry *dentry, const char *name, · 32 unmodified lines | ||
| 950 | 951 | if (!xattr) |
| 951 | 952 | goto out; |
| 952 | 953 | |
| 954 | + prealloc_cf = ceph_alloc_cap_flush(); | |
| 955 | + if (!prealloc_cf) | |
| 956 | + goto out; | |
| 957 | + | |
| 953 | 958 | spin_lock(&ci->i_ceph_lock); |
| 954 | 959 | retry: |
| 955 | 960 | issued = __ceph_caps_issued(ci, NULL); |
| @@ -991,7 +996,8 @@ retry: · 35 unmodified lines | ||
| 991 | 996 | flags, value ? 1 : -1, &xattr); |
| 992 | 997 | |
| 993 | 998 | if (!err) { |
| 994 | − dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); | |
| 999 | + dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL, | |
| 1000 | + &prealloc_cf); | |
| 995 | 1001 | ci->i_xattrs.dirty = true; |
| 996 | 1002 | inode->i_ctime = CURRENT_TIME; |
| 997 | 1003 | } |
| @@ -1001,6 +1007,7 @@ retry: · 3 unmodified lines | ||
| 1001 | 1007 | up_read(&mdsc->snap_rwsem); |
| 1002 | 1008 | if (dirty) |
| 1003 | 1009 | __mark_inode_dirty(inode, dirty); |
| 1010 | + ceph_free_cap_flush(prealloc_cf); | |
| 1004 | 1011 | return err; |
| 1005 | 1012 | |
| 1006 | 1013 | do_sync: |
| @@ -1010,6 +1017,7 @@ do_sync_unlocked: · 3 unmodified lines | ||
| 1010 | 1017 | up_read(&mdsc->snap_rwsem); |
| 1011 | 1018 | err = ceph_sync_setxattr(dentry, name, value, size, flags); |
| 1012 | 1019 | out: |
| 1020 | + ceph_free_cap_flush(prealloc_cf); | |
| 1013 | 1021 | kfree(newname); |
| 1014 | 1022 | kfree(newval); |
| 1015 | 1023 | kfree(xattr); |
| @@ -1062,6 +1070,7 @@ int __ceph_removexattr(struct dentry *dentry, const char *name) · 46 unmodified lines | ||
| 1062 | 1070 | struct ceph_vxattr *vxattr; |
| 1063 | 1071 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 1064 | 1072 | struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc; |
| 1073 | + struct ceph_cap_flush *prealloc_cf = NULL; | |
| 1065 | 1074 | int issued; |
| 1066 | 1075 | int err; |
| 1067 | 1076 | int required_blob_size; |
| @@ -1079,6 +1088,10 @@ int __ceph_removexattr(struct dentry *dentry, const char *name) · 11 unmodified lines | ||
| 1079 | 1088 | if (!strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN)) |
| 1080 | 1089 | goto do_sync_unlocked; |
| 1081 | 1090 | |
| 1091 | + prealloc_cf = ceph_alloc_cap_flush(); | |
| 1092 | + if (!prealloc_cf) | |
| 1093 | + return -ENOMEM; | |
| 1094 | + | |
| 1082 | 1095 | err = -ENOMEM; |
| 1083 | 1096 | spin_lock(&ci->i_ceph_lock); |
| 1084 | 1097 | retry: |
| @@ -1120,7 +1133,8 @@ retry: · 35 unmodified lines | ||
| 1120 | 1133 | |
| 1121 | 1134 | err = __remove_xattr_by_name(ceph_inode(inode), name); |
| 1122 | 1135 | |
| 1123 | − dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); | |
| 1136 | + dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL, | |
| 1137 | + &prealloc_cf); | |
| 1124 | 1138 | ci->i_xattrs.dirty = true; |
| 1125 | 1139 | inode->i_ctime = CURRENT_TIME; |
| 1126 | 1140 | spin_unlock(&ci->i_ceph_lock); |
| @@ -1128,12 +1142,14 @@ retry: · 1 unmodified line | ||
| 1128 | 1142 | up_read(&mdsc->snap_rwsem); |
| 1129 | 1143 | if (dirty) |
| 1130 | 1144 | __mark_inode_dirty(inode, dirty); |
| 1145 | + ceph_free_cap_flush(prealloc_cf); | |
| 1131 | 1146 | return err; |
| 1132 | 1147 | do_sync: |
| 1133 | 1148 | spin_unlock(&ci->i_ceph_lock); |
| 1134 | 1149 | do_sync_unlocked: |
| 1135 | 1150 | if (lock_snap_rwsem) |
| 1136 | 1151 | up_read(&mdsc->snap_rwsem); |
| 1152 | + ceph_free_cap_flush(prealloc_cf); | |
| 1137 | 1153 | err = ceph_send_removexattr(dentry, name); |
| 1138 | 1154 | return err; |
| 1139 | 1155 | } |
| @@ -174,6 +174,7 @@ static inline int calc_pages_for(u64 off, u64 len) · 173 unmodified lines | ||
| 174 | 174 | |
| 175 | 175 | extern struct kmem_cache *ceph_inode_cachep; |
| 176 | 176 | extern struct kmem_cache *ceph_cap_cachep; |
| 177 | +extern struct kmem_cache *ceph_cap_flush_cachep; | |
| 177 | 178 | extern struct kmem_cache *ceph_dentry_cachep; |
| 178 | 179 | extern struct kmem_cache *ceph_file_cachep; |
| 179 | 180 | |