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 | |
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')
-rw-r--r-- | fs/ceph/addr.c | 5 | ||||
-rw-r--r-- | fs/ceph/cache.c | 8 | ||||
-rw-r--r-- | fs/ceph/file.c | 30 | ||||
-rw-r--r-- | fs/ceph/inode.c | 8 |
4 files changed, 25 insertions, 26 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 6dfff0ba4d98..c22213789090 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
@@ -1108,7 +1108,7 @@ retry_locked: | |||
1108 | return 0; | 1108 | return 0; |
1109 | 1109 | ||
1110 | /* past end of file? */ | 1110 | /* past end of file? */ |
1111 | i_size = inode->i_size; /* caller holds i_mutex */ | 1111 | i_size = i_size_read(inode); |
1112 | 1112 | ||
1113 | if (page_off >= i_size || | 1113 | if (page_off >= i_size || |
1114 | (pos_in_page == 0 && (pos+len) >= i_size && | 1114 | (pos_in_page == 0 && (pos+len) >= i_size && |
@@ -1183,8 +1183,7 @@ static int ceph_write_end(struct file *file, struct address_space *mapping, | |||
1183 | zero_user_segment(page, from+copied, len); | 1183 | zero_user_segment(page, from+copied, len); |
1184 | 1184 | ||
1185 | /* did file size increase? */ | 1185 | /* did file size increase? */ |
1186 | /* (no need for i_size_read(); we caller holds i_mutex */ | 1186 | if (pos+copied > i_size_read(inode)) |
1187 | if (pos+copied > inode->i_size) | ||
1188 | check_cap = ceph_inode_set_size(inode, pos+copied); | 1187 | check_cap = ceph_inode_set_size(inode, pos+copied); |
1189 | 1188 | ||
1190 | if (!PageUptodate(page)) | 1189 | if (!PageUptodate(page)) |
diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c index a4766ded1ba7..16e7f7b60691 100644 --- a/fs/ceph/cache.c +++ b/fs/ceph/cache.c | |||
@@ -106,7 +106,7 @@ static uint16_t ceph_fscache_inode_get_aux(const void *cookie_netfs_data, | |||
106 | 106 | ||
107 | memset(&aux, 0, sizeof(aux)); | 107 | memset(&aux, 0, sizeof(aux)); |
108 | aux.mtime = inode->i_mtime; | 108 | aux.mtime = inode->i_mtime; |
109 | aux.size = inode->i_size; | 109 | aux.size = i_size_read(inode); |
110 | 110 | ||
111 | memcpy(buffer, &aux, sizeof(aux)); | 111 | memcpy(buffer, &aux, sizeof(aux)); |
112 | 112 | ||
@@ -117,9 +117,7 @@ static void ceph_fscache_inode_get_attr(const void *cookie_netfs_data, | |||
117 | uint64_t *size) | 117 | uint64_t *size) |
118 | { | 118 | { |
119 | const struct ceph_inode_info* ci = cookie_netfs_data; | 119 | const struct ceph_inode_info* ci = cookie_netfs_data; |
120 | const struct inode* inode = &ci->vfs_inode; | 120 | *size = i_size_read(&ci->vfs_inode); |
121 | |||
122 | *size = inode->i_size; | ||
123 | } | 121 | } |
124 | 122 | ||
125 | static enum fscache_checkaux ceph_fscache_inode_check_aux( | 123 | static enum fscache_checkaux ceph_fscache_inode_check_aux( |
@@ -134,7 +132,7 @@ static enum fscache_checkaux ceph_fscache_inode_check_aux( | |||
134 | 132 | ||
135 | memset(&aux, 0, sizeof(aux)); | 133 | memset(&aux, 0, sizeof(aux)); |
136 | aux.mtime = inode->i_mtime; | 134 | aux.mtime = inode->i_mtime; |
137 | aux.size = inode->i_size; | 135 | aux.size = i_size_read(inode); |
138 | 136 | ||
139 | if (memcmp(data, &aux, sizeof(aux)) != 0) | 137 | if (memcmp(data, &aux, sizeof(aux)) != 0) |
140 | return FSCACHE_CHECKAUX_OBSOLETE; | 138 | return FSCACHE_CHECKAUX_OBSOLETE; |
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 | ||
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 498dcfa2dcdb..eb7cb9176b0c 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -548,7 +548,7 @@ int ceph_fill_file_size(struct inode *inode, int issued, | |||
548 | if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) > 0 || | 548 | if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) > 0 || |
549 | (truncate_seq == ci->i_truncate_seq && size > inode->i_size)) { | 549 | (truncate_seq == ci->i_truncate_seq && size > inode->i_size)) { |
550 | dout("size %lld -> %llu\n", inode->i_size, size); | 550 | dout("size %lld -> %llu\n", inode->i_size, size); |
551 | inode->i_size = size; | 551 | i_size_write(inode, size); |
552 | inode->i_blocks = (size + (1<<9) - 1) >> 9; | 552 | inode->i_blocks = (size + (1<<9) - 1) >> 9; |
553 | ci->i_reported_size = size; | 553 | ci->i_reported_size = size; |
554 | if (truncate_seq != ci->i_truncate_seq) { | 554 | if (truncate_seq != ci->i_truncate_seq) { |
@@ -808,7 +808,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page, | |||
808 | spin_unlock(&ci->i_ceph_lock); | 808 | spin_unlock(&ci->i_ceph_lock); |
809 | 809 | ||
810 | err = -EINVAL; | 810 | err = -EINVAL; |
811 | if (WARN_ON(symlen != inode->i_size)) | 811 | if (WARN_ON(symlen != i_size_read(inode))) |
812 | goto out; | 812 | goto out; |
813 | 813 | ||
814 | err = -ENOMEM; | 814 | err = -ENOMEM; |
@@ -1549,7 +1549,7 @@ int ceph_inode_set_size(struct inode *inode, loff_t size) | |||
1549 | 1549 | ||
1550 | spin_lock(&ci->i_ceph_lock); | 1550 | spin_lock(&ci->i_ceph_lock); |
1551 | dout("set_size %p %llu -> %llu\n", inode, inode->i_size, size); | 1551 | dout("set_size %p %llu -> %llu\n", inode, inode->i_size, size); |
1552 | inode->i_size = size; | 1552 | i_size_write(inode, size); |
1553 | inode->i_blocks = (size + (1 << 9) - 1) >> 9; | 1553 | inode->i_blocks = (size + (1 << 9) - 1) >> 9; |
1554 | 1554 | ||
1555 | /* tell the MDS if we are approaching max_size */ | 1555 | /* tell the MDS if we are approaching max_size */ |
@@ -1911,7 +1911,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) | |||
1911 | inode->i_size, attr->ia_size); | 1911 | inode->i_size, attr->ia_size); |
1912 | if ((issued & CEPH_CAP_FILE_EXCL) && | 1912 | if ((issued & CEPH_CAP_FILE_EXCL) && |
1913 | attr->ia_size > inode->i_size) { | 1913 | attr->ia_size > inode->i_size) { |
1914 | inode->i_size = attr->ia_size; | 1914 | i_size_write(inode, attr->ia_size); |
1915 | inode->i_blocks = | 1915 | inode->i_blocks = |
1916 | (attr->ia_size + (1 << 9) - 1) >> 9; | 1916 | (attr->ia_size + (1 << 9) - 1) >> 9; |
1917 | inode->i_ctime = attr->ia_ctime; | 1917 | inode->i_ctime = attr->ia_ctime; |