diff options
Diffstat (limited to 'fs/ceph/addr.c')
-rw-r--r-- | fs/ceph/addr.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index f2c7aa878aa4..4a3f55f27ab4 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
@@ -1318,6 +1318,49 @@ out: | |||
1318 | return ret; | 1318 | return ret; |
1319 | } | 1319 | } |
1320 | 1320 | ||
1321 | void ceph_fill_inline_data(struct inode *inode, struct page *locked_page, | ||
1322 | char *data, size_t len) | ||
1323 | { | ||
1324 | struct address_space *mapping = inode->i_mapping; | ||
1325 | struct page *page; | ||
1326 | |||
1327 | if (locked_page) { | ||
1328 | page = locked_page; | ||
1329 | } else { | ||
1330 | if (i_size_read(inode) == 0) | ||
1331 | return; | ||
1332 | page = find_or_create_page(mapping, 0, | ||
1333 | mapping_gfp_mask(mapping) & ~__GFP_FS); | ||
1334 | if (!page) | ||
1335 | return; | ||
1336 | if (PageUptodate(page)) { | ||
1337 | unlock_page(page); | ||
1338 | page_cache_release(page); | ||
1339 | return; | ||
1340 | } | ||
1341 | } | ||
1342 | |||
1343 | dout("fill_inline_data %p %llx.%llx len %lu locked_page %p\n", | ||
1344 | inode, ceph_vinop(inode), len, locked_page); | ||
1345 | |||
1346 | if (len > 0) { | ||
1347 | void *kaddr = kmap_atomic(page); | ||
1348 | memcpy(kaddr, data, len); | ||
1349 | kunmap_atomic(kaddr); | ||
1350 | } | ||
1351 | |||
1352 | if (page != locked_page) { | ||
1353 | if (len < PAGE_CACHE_SIZE) | ||
1354 | zero_user_segment(page, len, PAGE_CACHE_SIZE); | ||
1355 | else | ||
1356 | flush_dcache_page(page); | ||
1357 | |||
1358 | SetPageUptodate(page); | ||
1359 | unlock_page(page); | ||
1360 | page_cache_release(page); | ||
1361 | } | ||
1362 | } | ||
1363 | |||
1321 | static struct vm_operations_struct ceph_vmops = { | 1364 | static struct vm_operations_struct ceph_vmops = { |
1322 | .fault = ceph_filemap_fault, | 1365 | .fault = ceph_filemap_fault, |
1323 | .page_mkwrite = ceph_page_mkwrite, | 1366 | .page_mkwrite = ceph_page_mkwrite, |