diff options
author | Josef Bacik <josef@redhat.com> | 2011-07-18 13:21:38 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-07-20 20:47:58 -0400 |
commit | 06222e491e663dac939f04b125c9dc52126a75c4 (patch) | |
tree | 99636fd666c8148a5bf58ea4844263d4b3a36310 /fs/ceph | |
parent | c334b1138bd44bea578eab7971c59bd9212a1093 (diff) |
fs: handle SEEK_HOLE/SEEK_DATA properly in all fs's that define their own llseek
This converts everybody to handle SEEK_HOLE/SEEK_DATA properly. In some cases
we just return -EINVAL, in others we do the normal generic thing, and in others
we're simply making sure that the properly due-dilligence is done. For example
in NFS/CIFS we need to make sure the file size is update properly for the
SEEK_HOLE and SEEK_DATA case, but since it calls the generic llseek stuff itself
that is all we have to do. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/dir.c | 8 | ||||
-rw-r--r-- | fs/ceph/file.c | 20 |
2 files changed, 25 insertions, 3 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index e8477dc51b45..0972b457a03f 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -446,14 +446,19 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin) | |||
446 | loff_t retval; | 446 | loff_t retval; |
447 | 447 | ||
448 | mutex_lock(&inode->i_mutex); | 448 | mutex_lock(&inode->i_mutex); |
449 | retval = -EINVAL; | ||
449 | switch (origin) { | 450 | switch (origin) { |
450 | case SEEK_END: | 451 | case SEEK_END: |
451 | offset += inode->i_size + 2; /* FIXME */ | 452 | offset += inode->i_size + 2; /* FIXME */ |
452 | break; | 453 | break; |
453 | case SEEK_CUR: | 454 | case SEEK_CUR: |
454 | offset += file->f_pos; | 455 | offset += file->f_pos; |
456 | case SEEK_SET: | ||
457 | break; | ||
458 | default: | ||
459 | goto out; | ||
455 | } | 460 | } |
456 | retval = -EINVAL; | 461 | |
457 | if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) { | 462 | if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) { |
458 | if (offset != file->f_pos) { | 463 | if (offset != file->f_pos) { |
459 | file->f_pos = offset; | 464 | file->f_pos = offset; |
@@ -477,6 +482,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin) | |||
477 | if (offset > old_offset) | 482 | if (offset > old_offset) |
478 | fi->dir_release_count--; | 483 | fi->dir_release_count--; |
479 | } | 484 | } |
485 | out: | ||
480 | mutex_unlock(&inode->i_mutex); | 486 | mutex_unlock(&inode->i_mutex); |
481 | return retval; | 487 | return retval; |
482 | } | 488 | } |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 0a292459c895..0d0eae05598f 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -768,13 +768,16 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin) | |||
768 | 768 | ||
769 | mutex_lock(&inode->i_mutex); | 769 | mutex_lock(&inode->i_mutex); |
770 | __ceph_do_pending_vmtruncate(inode); | 770 | __ceph_do_pending_vmtruncate(inode); |
771 | switch (origin) { | 771 | if (origin != SEEK_CUR || origin != SEEK_SET) { |
772 | case SEEK_END: | ||
773 | ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE); | 772 | ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE); |
774 | if (ret < 0) { | 773 | if (ret < 0) { |
775 | offset = ret; | 774 | offset = ret; |
776 | goto out; | 775 | goto out; |
777 | } | 776 | } |
777 | } | ||
778 | |||
779 | switch (origin) { | ||
780 | case SEEK_END: | ||
778 | offset += inode->i_size; | 781 | offset += inode->i_size; |
779 | break; | 782 | break; |
780 | case SEEK_CUR: | 783 | case SEEK_CUR: |
@@ -790,6 +793,19 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin) | |||
790 | } | 793 | } |
791 | offset += file->f_pos; | 794 | offset += file->f_pos; |
792 | break; | 795 | break; |
796 | case SEEK_DATA: | ||
797 | if (offset >= inode->i_size) { | ||
798 | ret = -ENXIO; | ||
799 | goto out; | ||
800 | } | ||
801 | break; | ||
802 | case SEEK_HOLE: | ||
803 | if (offset >= inode->i_size) { | ||
804 | ret = -ENXIO; | ||
805 | goto out; | ||
806 | } | ||
807 | offset = inode->i_size; | ||
808 | break; | ||
793 | } | 809 | } |
794 | 810 | ||
795 | if (offset < 0 || offset > inode->i_sb->s_maxbytes) { | 811 | if (offset < 0 || offset > inode->i_sb->s_maxbytes) { |