Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 276184
b: refs/heads/master
c: 93862d5
h: refs/heads/master
v: v3
  • Loading branch information
Sunil Mushran committed Jul 25, 2011
1 parent 264f313 commit e5eb55a
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5cffff9e29866a3de98c2c25135b3199491f93b0
refs/heads/master: 93862d5e1ab875664c6cc95254fc365028a48bb1
96 changes: 96 additions & 0 deletions trunk/fs/ocfs2/extent_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,102 @@ int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
return ret;
}

int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin)
{
struct inode *inode = file->f_mapping->host;
int ret;
unsigned int is_last = 0, is_data = 0;
u16 cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits;
u32 cpos, cend, clen, hole_size;
u64 extoff, extlen;
struct buffer_head *di_bh = NULL;
struct ocfs2_extent_rec rec;

BUG_ON(origin != SEEK_DATA && origin != SEEK_HOLE);

ret = ocfs2_inode_lock(inode, &di_bh, 0);
if (ret) {
mlog_errno(ret);
goto out;
}

down_read(&OCFS2_I(inode)->ip_alloc_sem);

if (*offset >= inode->i_size) {
ret = -ENXIO;
goto out_unlock;
}

if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
if (origin == SEEK_HOLE)
*offset = inode->i_size;
goto out_unlock;
}

clen = 0;
cpos = *offset >> cs_bits;
cend = ocfs2_clusters_for_bytes(inode->i_sb, inode->i_size);

while (cpos < cend && !is_last) {
ret = ocfs2_get_clusters_nocache(inode, di_bh, cpos, &hole_size,
&rec, &is_last);
if (ret) {
mlog_errno(ret);
goto out_unlock;
}

extoff = cpos;
extoff <<= cs_bits;

if (rec.e_blkno == 0ULL) {
clen = hole_size;
is_data = 0;
} else {
clen = le16_to_cpu(rec.e_leaf_clusters) -
(cpos - le32_to_cpu(rec.e_cpos));
is_data = (rec.e_flags & OCFS2_EXT_UNWRITTEN) ? 0 : 1;
}

if ((!is_data && origin == SEEK_HOLE) ||
(is_data && origin == SEEK_DATA)) {
if (extoff > *offset)
*offset = extoff;
goto out_unlock;
}

if (!is_last)
cpos += clen;
}

if (origin == SEEK_HOLE) {
extoff = cpos;
extoff <<= cs_bits;
extlen = clen;
extlen <<= cs_bits;

if ((extoff + extlen) > inode->i_size)
extlen = inode->i_size - extoff;
extoff += extlen;
if (extoff > *offset)
*offset = extoff;
goto out_unlock;
}

ret = -ENXIO;

out_unlock:

brelse(di_bh);

up_read(&OCFS2_I(inode)->ip_alloc_sem);

ocfs2_inode_unlock(inode, 0);
out:
if (ret && ret != -ENXIO)
ret = -ENXIO;
return ret;
}

int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
struct buffer_head *bhs[], int flags,
int (*validate)(struct super_block *sb,
Expand Down
2 changes: 2 additions & 0 deletions trunk/fs/ocfs2/extent_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 map_start, u64 map_len);

int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin);

int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
u32 *p_cluster, u32 *num_clusters,
struct ocfs2_extent_list *el,
Expand Down
55 changes: 53 additions & 2 deletions trunk/fs/ocfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2591,6 +2591,57 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
return ret;
}

/* Refer generic_file_llseek_unlocked() */
static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int origin)
{
struct inode *inode = file->f_mapping->host;
int ret = 0;

mutex_lock(&inode->i_mutex);

switch (origin) {
case SEEK_SET:
break;
case SEEK_END:
offset += inode->i_size;
break;
case SEEK_CUR:
if (offset == 0) {
offset = file->f_pos;
goto out;
}
offset += file->f_pos;
break;
case SEEK_DATA:
case SEEK_HOLE:
ret = ocfs2_seek_data_hole_offset(file, &offset, origin);
if (ret)
goto out;
break;
default:
ret = -EINVAL;
goto out;
}

if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
ret = -EINVAL;
if (!ret && offset > inode->i_sb->s_maxbytes)
ret = -EINVAL;
if (ret)
goto out;

if (offset != file->f_pos) {
file->f_pos = offset;
file->f_version = 0;
}

out:
mutex_unlock(&inode->i_mutex);
if (ret)
return ret;
return offset;
}

const struct inode_operations ocfs2_file_iops = {
.setattr = ocfs2_setattr,
.getattr = ocfs2_getattr,
Expand All @@ -2615,7 +2666,7 @@ const struct inode_operations ocfs2_special_file_iops = {
* ocfs2_fops_no_plocks and ocfs2_dops_no_plocks!
*/
const struct file_operations ocfs2_fops = {
.llseek = generic_file_llseek,
.llseek = ocfs2_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.mmap = ocfs2_mmap,
Expand Down Expand Up @@ -2663,7 +2714,7 @@ const struct file_operations ocfs2_dops = {
* the cluster.
*/
const struct file_operations ocfs2_fops_no_plocks = {
.llseek = generic_file_llseek,
.llseek = ocfs2_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.mmap = ocfs2_mmap,
Expand Down

0 comments on commit e5eb55a

Please sign in to comment.