diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ocfs2/aops.c | 24 | ||||
-rw-r--r-- | fs/ocfs2/cluster/heartbeat.c | 17 | ||||
-rw-r--r-- | fs/ocfs2/dlmglue.c | 10 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 13 |
4 files changed, 54 insertions, 10 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index ef6cd30108a9..93628b02ef5d 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -540,8 +540,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | |||
540 | struct buffer_head *bh_result, int create) | 540 | struct buffer_head *bh_result, int create) |
541 | { | 541 | { |
542 | int ret; | 542 | int ret; |
543 | u64 vbo_max; /* file offset, max_blocks from iblock */ | 543 | u64 p_blkno, inode_blocks; |
544 | u64 p_blkno; | ||
545 | int contig_blocks; | 544 | int contig_blocks; |
546 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; | 545 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; |
547 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; | 546 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; |
@@ -550,12 +549,23 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | |||
550 | * nicely aligned and of the right size, so there's no need | 549 | * nicely aligned and of the right size, so there's no need |
551 | * for us to check any of that. */ | 550 | * for us to check any of that. */ |
552 | 551 | ||
553 | vbo_max = ((u64)iblock + max_blocks) << blocksize_bits; | ||
554 | |||
555 | spin_lock(&OCFS2_I(inode)->ip_lock); | 552 | spin_lock(&OCFS2_I(inode)->ip_lock); |
556 | if ((iblock + max_blocks) > | 553 | inode_blocks = ocfs2_clusters_to_blocks(inode->i_sb, |
557 | ocfs2_clusters_to_blocks(inode->i_sb, | 554 | OCFS2_I(inode)->ip_clusters); |
558 | OCFS2_I(inode)->ip_clusters)) { | 555 | |
556 | /* | ||
557 | * For a read which begins past the end of file, we return a hole. | ||
558 | */ | ||
559 | if (!create && (iblock >= inode_blocks)) { | ||
560 | spin_unlock(&OCFS2_I(inode)->ip_lock); | ||
561 | ret = 0; | ||
562 | goto bail; | ||
563 | } | ||
564 | |||
565 | /* | ||
566 | * Any write past EOF is not allowed because we'd be extending. | ||
567 | */ | ||
568 | if (create && (iblock + max_blocks) > inode_blocks) { | ||
559 | spin_unlock(&OCFS2_I(inode)->ip_lock); | 569 | spin_unlock(&OCFS2_I(inode)->ip_lock); |
560 | ret = -EIO; | 570 | ret = -EIO; |
561 | goto bail; | 571 | goto bail; |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index a25ef5a50386..277ca67a2ad6 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -1447,6 +1447,15 @@ out: | |||
1447 | return ret; | 1447 | return ret; |
1448 | } | 1448 | } |
1449 | 1449 | ||
1450 | static ssize_t o2hb_region_pid_read(struct o2hb_region *reg, | ||
1451 | char *page) | ||
1452 | { | ||
1453 | if (!reg->hr_task) | ||
1454 | return 0; | ||
1455 | |||
1456 | return sprintf(page, "%u\n", reg->hr_task->pid); | ||
1457 | } | ||
1458 | |||
1450 | struct o2hb_region_attribute { | 1459 | struct o2hb_region_attribute { |
1451 | struct configfs_attribute attr; | 1460 | struct configfs_attribute attr; |
1452 | ssize_t (*show)(struct o2hb_region *, char *); | 1461 | ssize_t (*show)(struct o2hb_region *, char *); |
@@ -1485,11 +1494,19 @@ static struct o2hb_region_attribute o2hb_region_attr_dev = { | |||
1485 | .store = o2hb_region_dev_write, | 1494 | .store = o2hb_region_dev_write, |
1486 | }; | 1495 | }; |
1487 | 1496 | ||
1497 | static struct o2hb_region_attribute o2hb_region_attr_pid = { | ||
1498 | .attr = { .ca_owner = THIS_MODULE, | ||
1499 | .ca_name = "pid", | ||
1500 | .ca_mode = S_IRUGO | S_IRUSR }, | ||
1501 | .show = o2hb_region_pid_read, | ||
1502 | }; | ||
1503 | |||
1488 | static struct configfs_attribute *o2hb_region_attrs[] = { | 1504 | static struct configfs_attribute *o2hb_region_attrs[] = { |
1489 | &o2hb_region_attr_block_bytes.attr, | 1505 | &o2hb_region_attr_block_bytes.attr, |
1490 | &o2hb_region_attr_start_block.attr, | 1506 | &o2hb_region_attr_start_block.attr, |
1491 | &o2hb_region_attr_blocks.attr, | 1507 | &o2hb_region_attr_blocks.attr, |
1492 | &o2hb_region_attr_dev.attr, | 1508 | &o2hb_region_attr_dev.attr, |
1509 | &o2hb_region_attr_pid.attr, | ||
1493 | NULL, | 1510 | NULL, |
1494 | }; | 1511 | }; |
1495 | 1512 | ||
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index e6220137bf69..e335541727f9 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -2718,6 +2718,15 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, | |||
2718 | inode = ocfs2_lock_res_inode(lockres); | 2718 | inode = ocfs2_lock_res_inode(lockres); |
2719 | mapping = inode->i_mapping; | 2719 | mapping = inode->i_mapping; |
2720 | 2720 | ||
2721 | /* | ||
2722 | * We need this before the filemap_fdatawrite() so that it can | ||
2723 | * transfer the dirty bit from the PTE to the | ||
2724 | * page. Unfortunately this means that even for EX->PR | ||
2725 | * downconverts, we'll lose our mappings and have to build | ||
2726 | * them up again. | ||
2727 | */ | ||
2728 | unmap_mapping_range(mapping, 0, 0, 0); | ||
2729 | |||
2721 | if (filemap_fdatawrite(mapping)) { | 2730 | if (filemap_fdatawrite(mapping)) { |
2722 | mlog(ML_ERROR, "Could not sync inode %llu for downconvert!", | 2731 | mlog(ML_ERROR, "Could not sync inode %llu for downconvert!", |
2723 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 2732 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
@@ -2725,7 +2734,6 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, | |||
2725 | sync_mapping_buffers(mapping); | 2734 | sync_mapping_buffers(mapping); |
2726 | if (blocking == LKM_EXMODE) { | 2735 | if (blocking == LKM_EXMODE) { |
2727 | truncate_inode_pages(mapping, 0); | 2736 | truncate_inode_pages(mapping, 0); |
2728 | unmap_mapping_range(mapping, 0, 0, 0); | ||
2729 | } else { | 2737 | } else { |
2730 | /* We only need to wait on the I/O if we're not also | 2738 | /* We only need to wait on the I/O if we're not also |
2731 | * truncating pages because truncate_inode_pages waits | 2739 | * truncating pages because truncate_inode_pages waits |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 9fd590b9bde3..10953a508f2f 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -149,6 +149,17 @@ int ocfs2_should_update_atime(struct inode *inode, | |||
149 | ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))) | 149 | ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))) |
150 | return 0; | 150 | return 0; |
151 | 151 | ||
152 | /* | ||
153 | * We can be called with no vfsmnt structure - NFSD will | ||
154 | * sometimes do this. | ||
155 | * | ||
156 | * Note that our action here is different than touch_atime() - | ||
157 | * if we can't tell whether this is a noatime mount, then we | ||
158 | * don't know whether to trust the value of s_atime_quantum. | ||
159 | */ | ||
160 | if (vfsmnt == NULL) | ||
161 | return 0; | ||
162 | |||
152 | if ((vfsmnt->mnt_flags & MNT_NOATIME) || | 163 | if ((vfsmnt->mnt_flags & MNT_NOATIME) || |
153 | ((vfsmnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))) | 164 | ((vfsmnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))) |
154 | return 0; | 165 | return 0; |
@@ -966,8 +977,6 @@ int ocfs2_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
966 | } | 977 | } |
967 | 978 | ||
968 | ret = generic_permission(inode, mask, NULL); | 979 | ret = generic_permission(inode, mask, NULL); |
969 | if (ret) | ||
970 | mlog_errno(ret); | ||
971 | 980 | ||
972 | ocfs2_meta_unlock(inode, 0); | 981 | ocfs2_meta_unlock(inode, 0); |
973 | out: | 982 | out: |