Skip to content

Commit b11ed50

Browse files
jtlaytonidryomov
authored andcommitted
ceph: request Fw caps before updating the mtime in ceph_write_iter
The current code will update the mtime and then try to get caps to handle the write. If we end up having to request caps from the MDS, then the mtime in the cap grant will clobber the updated mtime and it'll be lost. This is most noticable when two clients are alternately writing to the same file. Fw caps are continually being granted and revoked, and the mtime ends up stuck because the updated mtimes are always being overwritten with the old one. Fix this by changing the order of operations in ceph_write_iter to get the caps before updating the times. Also, make sure we check the pool full conditions before even getting any caps or uninlining. URL: https://tracker.ceph.com/issues/46574 Reported-by: Jozef Kováč <[email protected]> Signed-off-by: Jeff Layton <[email protected]> Reviewed-by: Xiubo Li <[email protected]> Reviewed-by: Luis Henriques <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent d517b39 commit b11ed50

File tree

1 file changed

+17
-15
lines changed

1 file changed

+17
-15
lines changed

fs/ceph/file.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,32 +1722,26 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
17221722
goto out;
17231723
}
17241724

1725-
err = file_remove_privs(file);
1726-
if (err)
1725+
down_read(&osdc->lock);
1726+
map_flags = osdc->osdmap->flags;
1727+
pool_flags = ceph_pg_pool_flags(osdc->osdmap, ci->i_layout.pool_id);
1728+
up_read(&osdc->lock);
1729+
if ((map_flags & CEPH_OSDMAP_FULL) ||
1730+
(pool_flags & CEPH_POOL_FLAG_FULL)) {
1731+
err = -ENOSPC;
17271732
goto out;
1733+
}
17281734

1729-
err = file_update_time(file);
1735+
err = file_remove_privs(file);
17301736
if (err)
17311737
goto out;
17321738

1733-
inode_inc_iversion_raw(inode);
1734-
17351739
if (ci->i_inline_version != CEPH_INLINE_NONE) {
17361740
err = ceph_uninline_data(file, NULL);
17371741
if (err < 0)
17381742
goto out;
17391743
}
17401744

1741-
down_read(&osdc->lock);
1742-
map_flags = osdc->osdmap->flags;
1743-
pool_flags = ceph_pg_pool_flags(osdc->osdmap, ci->i_layout.pool_id);
1744-
up_read(&osdc->lock);
1745-
if ((map_flags & CEPH_OSDMAP_FULL) ||
1746-
(pool_flags & CEPH_POOL_FLAG_FULL)) {
1747-
err = -ENOSPC;
1748-
goto out;
1749-
}
1750-
17511745
dout("aio_write %p %llx.%llx %llu~%zd getting caps. i_size %llu\n",
17521746
inode, ceph_vinop(inode), pos, count, i_size_read(inode));
17531747
if (fi->fmode & CEPH_FILE_MODE_LAZY)
@@ -1759,6 +1753,12 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
17591753
if (err < 0)
17601754
goto out;
17611755

1756+
err = file_update_time(file);
1757+
if (err)
1758+
goto out_caps;
1759+
1760+
inode_inc_iversion_raw(inode);
1761+
17621762
dout("aio_write %p %llx.%llx %llu~%zd got cap refs on %s\n",
17631763
inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
17641764

@@ -1842,6 +1842,8 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
18421842
}
18431843

18441844
goto out_unlocked;
1845+
out_caps:
1846+
ceph_put_cap_refs(ci, got);
18451847
out:
18461848
if (direct_lock)
18471849
ceph_end_io_direct(inode);

0 commit comments

Comments
 (0)