aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/file.c
diff options
context:
space:
mode:
authorSunil Mushran <sunil.mushran@oracle.com>2011-07-25 17:58:15 -0400
committerSunil Mushran <sunil.mushran@oracle.com>2011-07-25 17:58:15 -0400
commit93862d5e1ab875664c6cc95254fc365028a48bb1 (patch)
tree3299a37486b2265e051a4c641aa7cfbb309a69d6 /fs/ocfs2/file.c
parent5cffff9e29866a3de98c2c25135b3199491f93b0 (diff)
ocfs2: Implement llseek()
ocfs2 implements its own llseek() to provide the SEEK_HOLE/SEEK_DATA functionality. SEEK_HOLE sets the file pointer to the start of either a hole or an unwritten (preallocated) extent, that is greater than or equal to the supplied offset. SEEK_DATA sets the file pointer to the start of an allocated extent (not unwritten) that is greater than or equal to the supplied offset. If the supplied offset is on a desired region, then the file pointer is set to it. Offsets greater than or equal to the file size return -ENXIO. Unwritten (preallocated) extents are considered holes because the file system treats reads to such regions in the same way as it does to holes. Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com>
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r--fs/ocfs2/file.c55
1 files changed, 53 insertions, 2 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 0fc2bd34039d..c0f015e11c28 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2591,6 +2591,57 @@ bail:
2591 return ret; 2591 return ret;
2592} 2592}
2593 2593
2594/* Refer generic_file_llseek_unlocked() */
2595static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int origin)
2596{
2597 struct inode *inode = file->f_mapping->host;
2598 int ret = 0;
2599
2600 mutex_lock(&inode->i_mutex);
2601
2602 switch (origin) {
2603 case SEEK_SET:
2604 break;
2605 case SEEK_END:
2606 offset += inode->i_size;
2607 break;
2608 case SEEK_CUR:
2609 if (offset == 0) {
2610 offset = file->f_pos;
2611 goto out;
2612 }
2613 offset += file->f_pos;
2614 break;
2615 case SEEK_DATA:
2616 case SEEK_HOLE:
2617 ret = ocfs2_seek_data_hole_offset(file, &offset, origin);
2618 if (ret)
2619 goto out;
2620 break;
2621 default:
2622 ret = -EINVAL;
2623 goto out;
2624 }
2625
2626 if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
2627 ret = -EINVAL;
2628 if (!ret && offset > inode->i_sb->s_maxbytes)
2629 ret = -EINVAL;
2630 if (ret)
2631 goto out;
2632
2633 if (offset != file->f_pos) {
2634 file->f_pos = offset;
2635 file->f_version = 0;
2636 }
2637
2638out:
2639 mutex_unlock(&inode->i_mutex);
2640 if (ret)
2641 return ret;
2642 return offset;
2643}
2644
2594const struct inode_operations ocfs2_file_iops = { 2645const struct inode_operations ocfs2_file_iops = {
2595 .setattr = ocfs2_setattr, 2646 .setattr = ocfs2_setattr,
2596 .getattr = ocfs2_getattr, 2647 .getattr = ocfs2_getattr,
@@ -2615,7 +2666,7 @@ const struct inode_operations ocfs2_special_file_iops = {
2615 * ocfs2_fops_no_plocks and ocfs2_dops_no_plocks! 2666 * ocfs2_fops_no_plocks and ocfs2_dops_no_plocks!
2616 */ 2667 */
2617const struct file_operations ocfs2_fops = { 2668const struct file_operations ocfs2_fops = {
2618 .llseek = generic_file_llseek, 2669 .llseek = ocfs2_file_llseek,
2619 .read = do_sync_read, 2670 .read = do_sync_read,
2620 .write = do_sync_write, 2671 .write = do_sync_write,
2621 .mmap = ocfs2_mmap, 2672 .mmap = ocfs2_mmap,
@@ -2663,7 +2714,7 @@ const struct file_operations ocfs2_dops = {
2663 * the cluster. 2714 * the cluster.
2664 */ 2715 */
2665const struct file_operations ocfs2_fops_no_plocks = { 2716const struct file_operations ocfs2_fops_no_plocks = {
2666 .llseek = generic_file_llseek, 2717 .llseek = ocfs2_file_llseek,
2667 .read = do_sync_read, 2718 .read = do_sync_read,
2668 .write = do_sync_write, 2719 .write = do_sync_write,
2669 .mmap = ocfs2_mmap, 2720 .mmap = ocfs2_mmap,