diff options
author | Sunil Mushran <sunil.mushran@oracle.com> | 2011-07-25 17:58:15 -0400 |
---|---|---|
committer | Sunil Mushran <sunil.mushran@oracle.com> | 2011-07-25 17:58:15 -0400 |
commit | 93862d5e1ab875664c6cc95254fc365028a48bb1 (patch) | |
tree | 3299a37486b2265e051a4c641aa7cfbb309a69d6 /fs/ocfs2/file.c | |
parent | 5cffff9e29866a3de98c2c25135b3199491f93b0 (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.c | 55 |
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() */ | ||
2595 | static 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 | |||
2638 | out: | ||
2639 | mutex_unlock(&inode->i_mutex); | ||
2640 | if (ret) | ||
2641 | return ret; | ||
2642 | return offset; | ||
2643 | } | ||
2644 | |||
2594 | const struct inode_operations ocfs2_file_iops = { | 2645 | const 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 | */ |
2617 | const struct file_operations ocfs2_fops = { | 2668 | const 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 | */ |
2665 | const struct file_operations ocfs2_fops_no_plocks = { | 2716 | const 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, |