diff options
| author | Yan, Zheng <zyan@redhat.com> | 2015-12-29 22:32:46 -0500 |
|---|---|---|
| committer | Ilya Dryomov <idryomov@gmail.com> | 2016-01-21 13:36:08 -0500 |
| commit | 99c88e6900fb05d267ae9f6d5e15dc7192ba6f8d (patch) | |
| tree | 025263471172932f2c0b332979cf56c60ae836db /fs/ceph/file.c | |
| parent | 5be0389dac662995eade757ec678931f0be23d33 (diff) | |
ceph: use i_size_{read,write} to get/set i_size
Cap message from MDS can update i_size. In that case, we don't
hold i_mutex. So it's unsafe to directly access inode->i_size
while holding i_mutex.
Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/file.c')
| -rw-r--r-- | fs/ceph/file.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 41c2267b4b7e..d37efdd8533d 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
| @@ -417,6 +417,7 @@ static int striped_read(struct inode *inode, | |||
| 417 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); | 417 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
| 418 | struct ceph_inode_info *ci = ceph_inode(inode); | 418 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 419 | u64 pos, this_len, left; | 419 | u64 pos, this_len, left; |
| 420 | loff_t i_size; | ||
| 420 | int page_align, pages_left; | 421 | int page_align, pages_left; |
| 421 | int read, ret; | 422 | int read, ret; |
| 422 | struct page **page_pos; | 423 | struct page **page_pos; |
| @@ -446,11 +447,11 @@ more: | |||
| 446 | dout("striped_read %llu~%llu (read %u) got %d%s%s\n", pos, left, read, | 447 | dout("striped_read %llu~%llu (read %u) got %d%s%s\n", pos, left, read, |
| 447 | ret, hit_stripe ? " HITSTRIPE" : "", was_short ? " SHORT" : ""); | 448 | ret, hit_stripe ? " HITSTRIPE" : "", was_short ? " SHORT" : ""); |
| 448 | 449 | ||
| 450 | i_size = i_size_read(inode); | ||
| 449 | if (ret >= 0) { | 451 | if (ret >= 0) { |
| 450 | int didpages; | 452 | int didpages; |
| 451 | if (was_short && (pos + ret < inode->i_size)) { | 453 | if (was_short && (pos + ret < i_size)) { |
| 452 | int zlen = min(this_len - ret, | 454 | int zlen = min(this_len - ret, i_size - pos - ret); |
| 453 | inode->i_size - pos - ret); | ||
| 454 | int zoff = (off & ~PAGE_MASK) + read + ret; | 455 | int zoff = (off & ~PAGE_MASK) + read + ret; |
| 455 | dout(" zero gap %llu to %llu\n", | 456 | dout(" zero gap %llu to %llu\n", |
| 456 | pos + ret, pos + ret + zlen); | 457 | pos + ret, pos + ret + zlen); |
| @@ -466,14 +467,14 @@ more: | |||
| 466 | pages_left -= didpages; | 467 | pages_left -= didpages; |
| 467 | 468 | ||
| 468 | /* hit stripe and need continue*/ | 469 | /* hit stripe and need continue*/ |
| 469 | if (left && hit_stripe && pos < inode->i_size) | 470 | if (left && hit_stripe && pos < i_size) |
| 470 | goto more; | 471 | goto more; |
| 471 | } | 472 | } |
| 472 | 473 | ||
| 473 | if (read > 0) { | 474 | if (read > 0) { |
| 474 | ret = read; | 475 | ret = read; |
| 475 | /* did we bounce off eof? */ | 476 | /* did we bounce off eof? */ |
| 476 | if (pos + left > inode->i_size) | 477 | if (pos + left > i_size) |
| 477 | *checkeof = CHECK_EOF; | 478 | *checkeof = CHECK_EOF; |
| 478 | } | 479 | } |
| 479 | 480 | ||
| @@ -1209,8 +1210,7 @@ again: | |||
| 1209 | if (retry_op == CHECK_EOF && iocb->ki_pos < i_size && | 1210 | if (retry_op == CHECK_EOF && iocb->ki_pos < i_size && |
| 1210 | ret < len) { | 1211 | ret < len) { |
| 1211 | dout("sync_read hit hole, ppos %lld < size %lld" | 1212 | dout("sync_read hit hole, ppos %lld < size %lld" |
| 1212 | ", reading more\n", iocb->ki_pos, | 1213 | ", reading more\n", iocb->ki_pos, i_size); |
| 1213 | inode->i_size); | ||
| 1214 | 1214 | ||
| 1215 | read += ret; | 1215 | read += ret; |
| 1216 | len -= ret; | 1216 | len -= ret; |
| @@ -1293,7 +1293,7 @@ retry_snap: | |||
| 1293 | } | 1293 | } |
| 1294 | 1294 | ||
| 1295 | dout("aio_write %p %llx.%llx %llu~%zd getting caps. i_size %llu\n", | 1295 | dout("aio_write %p %llx.%llx %llu~%zd getting caps. i_size %llu\n", |
| 1296 | inode, ceph_vinop(inode), pos, count, inode->i_size); | 1296 | inode, ceph_vinop(inode), pos, count, i_size_read(inode)); |
| 1297 | if (fi->fmode & CEPH_FILE_MODE_LAZY) | 1297 | if (fi->fmode & CEPH_FILE_MODE_LAZY) |
| 1298 | want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO; | 1298 | want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO; |
| 1299 | else | 1299 | else |
| @@ -1345,7 +1345,7 @@ retry_snap: | |||
| 1345 | iov_iter_advance(from, written); | 1345 | iov_iter_advance(from, written); |
| 1346 | ceph_put_snap_context(snapc); | 1346 | ceph_put_snap_context(snapc); |
| 1347 | } else { | 1347 | } else { |
| 1348 | loff_t old_size = inode->i_size; | 1348 | loff_t old_size = i_size_read(inode); |
| 1349 | /* | 1349 | /* |
| 1350 | * No need to acquire the i_truncate_mutex. Because | 1350 | * No need to acquire the i_truncate_mutex. Because |
| 1351 | * the MDS revokes Fwb caps before sending truncate | 1351 | * the MDS revokes Fwb caps before sending truncate |
| @@ -1356,7 +1356,7 @@ retry_snap: | |||
| 1356 | written = generic_perform_write(file, from, pos); | 1356 | written = generic_perform_write(file, from, pos); |
| 1357 | if (likely(written >= 0)) | 1357 | if (likely(written >= 0)) |
| 1358 | iocb->ki_pos = pos + written; | 1358 | iocb->ki_pos = pos + written; |
| 1359 | if (inode->i_size > old_size) | 1359 | if (i_size_read(inode) > old_size) |
| 1360 | ceph_fscache_update_objectsize(inode); | 1360 | ceph_fscache_update_objectsize(inode); |
| 1361 | mutex_unlock(&inode->i_mutex); | 1361 | mutex_unlock(&inode->i_mutex); |
| 1362 | } | 1362 | } |
| @@ -1401,6 +1401,7 @@ out_unlocked: | |||
| 1401 | static loff_t ceph_llseek(struct file *file, loff_t offset, int whence) | 1401 | static loff_t ceph_llseek(struct file *file, loff_t offset, int whence) |
| 1402 | { | 1402 | { |
| 1403 | struct inode *inode = file->f_mapping->host; | 1403 | struct inode *inode = file->f_mapping->host; |
| 1404 | loff_t i_size; | ||
| 1404 | int ret; | 1405 | int ret; |
| 1405 | 1406 | ||
| 1406 | mutex_lock(&inode->i_mutex); | 1407 | mutex_lock(&inode->i_mutex); |
| @@ -1413,9 +1414,10 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int whence) | |||
| 1413 | } | 1414 | } |
| 1414 | } | 1415 | } |
| 1415 | 1416 | ||
| 1417 | i_size = i_size_read(inode); | ||
| 1416 | switch (whence) { | 1418 | switch (whence) { |
| 1417 | case SEEK_END: | 1419 | case SEEK_END: |
| 1418 | offset += inode->i_size; | 1420 | offset += i_size; |
| 1419 | break; | 1421 | break; |
| 1420 | case SEEK_CUR: | 1422 | case SEEK_CUR: |
| 1421 | /* | 1423 | /* |
| @@ -1431,17 +1433,17 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int whence) | |||
| 1431 | offset += file->f_pos; | 1433 | offset += file->f_pos; |
| 1432 | break; | 1434 | break; |
| 1433 | case SEEK_DATA: | 1435 | case SEEK_DATA: |
| 1434 | if (offset >= inode->i_size) { | 1436 | if (offset >= i_size) { |
| 1435 | ret = -ENXIO; | 1437 | ret = -ENXIO; |
| 1436 | goto out; | 1438 | goto out; |
| 1437 | } | 1439 | } |
| 1438 | break; | 1440 | break; |
| 1439 | case SEEK_HOLE: | 1441 | case SEEK_HOLE: |
| 1440 | if (offset >= inode->i_size) { | 1442 | if (offset >= i_size) { |
| 1441 | ret = -ENXIO; | 1443 | ret = -ENXIO; |
| 1442 | goto out; | 1444 | goto out; |
| 1443 | } | 1445 | } |
| 1444 | offset = inode->i_size; | 1446 | offset = i_size; |
| 1445 | break; | 1447 | break; |
| 1446 | } | 1448 | } |
| 1447 | 1449 | ||
