aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/file.c
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-05-08 20:47:32 -0400
committerMark Fasheh <mark.fasheh@oracle.com>2007-07-10 20:31:46 -0400
commit3a307ffc2730bfa1a4dfa94537be9d412338aad2 (patch)
tree3e83201eb816aec8b897afcf3920dd716ce4412c /fs/ocfs2/file.c
parent2e89b2e48e1da09ed483f195968c9172aa95b5e2 (diff)
ocfs2: rework ocfs2_buffered_write_cluster()
Use some ideas from the new-aops patch series and turn ocfs2_buffered_write_cluster() into a 2 stage operation with the caller copying data in between. The code now understands multiple cluster writes as a result of having to deal with a full page write for greater than 4k pages. This sets us up to easily call into the write path during ->page_mkwrite(). Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r--fs/ocfs2/file.c121
1 files changed, 67 insertions, 54 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 566f9b70ec91..4c850d00c269 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1335,15 +1335,16 @@ ocfs2_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
1335 *basep = base; 1335 *basep = base;
1336} 1336}
1337 1337
1338static struct page * ocfs2_get_write_source(struct ocfs2_buffered_write_priv *bp, 1338static struct page * ocfs2_get_write_source(char **ret_src_buf,
1339 const struct iovec *cur_iov, 1339 const struct iovec *cur_iov,
1340 size_t iov_offset) 1340 size_t iov_offset)
1341{ 1341{
1342 int ret; 1342 int ret;
1343 char *buf; 1343 char *buf = cur_iov->iov_base + iov_offset;
1344 struct page *src_page = NULL; 1344 struct page *src_page = NULL;
1345 unsigned long off;
1345 1346
1346 buf = cur_iov->iov_base + iov_offset; 1347 off = (unsigned long)(buf) & ~PAGE_CACHE_MASK;
1347 1348
1348 if (!segment_eq(get_fs(), KERNEL_DS)) { 1349 if (!segment_eq(get_fs(), KERNEL_DS)) {
1349 /* 1350 /*
@@ -1355,18 +1356,17 @@ static struct page * ocfs2_get_write_source(struct ocfs2_buffered_write_priv *bp
1355 (unsigned long)buf & PAGE_CACHE_MASK, 1, 1356 (unsigned long)buf & PAGE_CACHE_MASK, 1,
1356 0, 0, &src_page, NULL); 1357 0, 0, &src_page, NULL);
1357 if (ret == 1) 1358 if (ret == 1)
1358 bp->b_src_buf = kmap(src_page); 1359 *ret_src_buf = kmap(src_page) + off;
1359 else 1360 else
1360 src_page = ERR_PTR(-EFAULT); 1361 src_page = ERR_PTR(-EFAULT);
1361 } else { 1362 } else {
1362 bp->b_src_buf = buf; 1363 *ret_src_buf = buf;
1363 } 1364 }
1364 1365
1365 return src_page; 1366 return src_page;
1366} 1367}
1367 1368
1368static void ocfs2_put_write_source(struct ocfs2_buffered_write_priv *bp, 1369static void ocfs2_put_write_source(struct page *page)
1369 struct page *page)
1370{ 1370{
1371 if (page) { 1371 if (page) {
1372 kunmap(page); 1372 kunmap(page);
@@ -1382,10 +1382,12 @@ static ssize_t ocfs2_file_buffered_write(struct file *file, loff_t *ppos,
1382{ 1382{
1383 int ret = 0; 1383 int ret = 0;
1384 ssize_t copied, total = 0; 1384 ssize_t copied, total = 0;
1385 size_t iov_offset = 0; 1385 size_t iov_offset = 0, bytes;
1386 loff_t pos;
1386 const struct iovec *cur_iov = iov; 1387 const struct iovec *cur_iov = iov;
1387 struct ocfs2_buffered_write_priv bp; 1388 struct page *user_page, *page;
1388 struct page *page; 1389 char *buf, *dst;
1390 void *fsdata;
1389 1391
1390 /* 1392 /*
1391 * handle partial DIO write. Adjust cur_iov if needed. 1393 * handle partial DIO write. Adjust cur_iov if needed.
@@ -1393,21 +1395,38 @@ static ssize_t ocfs2_file_buffered_write(struct file *file, loff_t *ppos,
1393 ocfs2_set_next_iovec(&cur_iov, &iov_offset, o_direct_written); 1395 ocfs2_set_next_iovec(&cur_iov, &iov_offset, o_direct_written);
1394 1396
1395 do { 1397 do {
1396 bp.b_cur_off = iov_offset; 1398 pos = *ppos;
1397 bp.b_cur_iov = cur_iov;
1398 1399
1399 page = ocfs2_get_write_source(&bp, cur_iov, iov_offset); 1400 user_page = ocfs2_get_write_source(&buf, cur_iov, iov_offset);
1400 if (IS_ERR(page)) { 1401 if (IS_ERR(user_page)) {
1401 ret = PTR_ERR(page); 1402 ret = PTR_ERR(user_page);
1402 goto out; 1403 goto out;
1403 } 1404 }
1404 1405
1405 copied = ocfs2_buffered_write_cluster(file, *ppos, count, 1406 /* Stay within our page boundaries */
1406 ocfs2_map_and_write_user_data, 1407 bytes = min((PAGE_CACHE_SIZE - ((unsigned long)pos & ~PAGE_CACHE_MASK)),
1407 &bp); 1408 (PAGE_CACHE_SIZE - ((unsigned long)buf & ~PAGE_CACHE_MASK)));
1409 /* Stay within the vector boundary */
1410 bytes = min_t(size_t, bytes, cur_iov->iov_len - iov_offset);
1411 /* Stay within count */
1412 bytes = min(bytes, count);
1413
1414 page = NULL;
1415 ret = ocfs2_write_begin(file, file->f_mapping, pos, bytes, 0,
1416 &page, &fsdata);
1417 if (ret) {
1418 mlog_errno(ret);
1419 goto out;
1420 }
1408 1421
1409 ocfs2_put_write_source(&bp, page); 1422 dst = kmap_atomic(page, KM_USER0);
1423 memcpy(dst + (pos & (PAGE_CACHE_SIZE - 1)), buf, bytes);
1424 kunmap_atomic(dst, KM_USER0);
1425 flush_dcache_page(page);
1426 ocfs2_put_write_source(user_page);
1410 1427
1428 copied = ocfs2_write_end(file, file->f_mapping, pos, bytes,
1429 bytes, page, fsdata);
1411 if (copied < 0) { 1430 if (copied < 0) {
1412 mlog_errno(copied); 1431 mlog_errno(copied);
1413 ret = copied; 1432 ret = copied;
@@ -1415,7 +1434,7 @@ static ssize_t ocfs2_file_buffered_write(struct file *file, loff_t *ppos,
1415 } 1434 }
1416 1435
1417 total += copied; 1436 total += copied;
1418 *ppos = *ppos + copied; 1437 *ppos = pos + copied;
1419 count -= copied; 1438 count -= copied;
1420 1439
1421 ocfs2_set_next_iovec(&cur_iov, &iov_offset, copied); 1440 ocfs2_set_next_iovec(&cur_iov, &iov_offset, copied);
@@ -1585,52 +1604,46 @@ static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe,
1585 struct pipe_buffer *buf, 1604 struct pipe_buffer *buf,
1586 struct splice_desc *sd) 1605 struct splice_desc *sd)
1587{ 1606{
1588 int ret, count, total = 0; 1607 int ret, count;
1589 ssize_t copied = 0; 1608 ssize_t copied = 0;
1590 struct ocfs2_splice_write_priv sp; 1609 struct file *file = sd->u.file;
1610 unsigned int offset;
1611 struct page *page = NULL;
1612 void *fsdata;
1613 char *src, *dst;
1591 1614
1592 ret = buf->ops->confirm(pipe, buf); 1615 ret = buf->ops->confirm(pipe, buf);
1593 if (ret) 1616 if (ret)
1594 goto out; 1617 goto out;
1595 1618
1596 sp.s_sd = sd; 1619 offset = sd->pos & ~PAGE_CACHE_MASK;
1597 sp.s_buf = buf;
1598 sp.s_pipe = pipe;
1599 sp.s_offset = sd->pos & ~PAGE_CACHE_MASK;
1600 sp.s_buf_offset = buf->offset;
1601
1602 count = sd->len; 1620 count = sd->len;
1603 if (count + sp.s_offset > PAGE_CACHE_SIZE) 1621 if (count + offset > PAGE_CACHE_SIZE)
1604 count = PAGE_CACHE_SIZE - sp.s_offset; 1622 count = PAGE_CACHE_SIZE - offset;
1605 1623
1606 do { 1624 ret = ocfs2_write_begin(file, file->f_mapping, sd->pos, count, 0,
1607 /* 1625 &page, &fsdata);
1608 * splice wants us to copy up to one page at a 1626 if (ret) {
1609 * time. For pagesize > cluster size, this means we 1627 mlog_errno(ret);
1610 * might enter ocfs2_buffered_write_cluster() more 1628 goto out;
1611 * than once, so keep track of our progress here. 1629 }
1612 */
1613 copied = ocfs2_buffered_write_cluster(sd->u.file,
1614 (loff_t)sd->pos + total,
1615 count,
1616 ocfs2_map_and_write_splice_data,
1617 &sp);
1618 if (copied < 0) {
1619 mlog_errno(copied);
1620 ret = copied;
1621 goto out;
1622 }
1623 1630
1624 count -= copied; 1631 src = buf->ops->map(pipe, buf, 1);
1625 sp.s_offset += copied; 1632 dst = kmap_atomic(page, KM_USER1);
1626 sp.s_buf_offset += copied; 1633 memcpy(dst + offset, src + buf->offset, count);
1627 total += copied; 1634 kunmap_atomic(page, KM_USER1);
1628 } while (count); 1635 buf->ops->unmap(pipe, buf, src);
1629 1636
1630 ret = 0; 1637 copied = ocfs2_write_end(file, file->f_mapping, sd->pos, count, count,
1638 page, fsdata);
1639 if (copied < 0) {
1640 mlog_errno(copied);
1641 ret = copied;
1642 goto out;
1643 }
1631out: 1644out:
1632 1645
1633 return total ? total : ret; 1646 return copied ? copied : ret;
1634} 1647}
1635 1648
1636static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe, 1649static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe,