diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-03-22 11:15:45 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-03-22 11:15:45 -0700 |
commit | ff9c18e435b042596c9d48badac7488e3fa76a55 (patch) | |
tree | 08d9668e38b74d01db0259457aa20c133034dffa /fs | |
parent | 6f6efce52d3a035b8332969ecf254b4dfc62e4ec (diff) | |
parent | 825b82f6b82aa38dbb771d24e135152012500e51 (diff) |
Merge tag 'ceph-for-6.9-rc1' of https://github.com/ceph/ceph-client
Pull ceph updates from Ilya Dryomov:
"A patch to minimize blockage when processing very large batches of
dirty caps and two fixes to better handle EOF in the face of multiple
clients performing reads and size-extending writes at the same time"
* tag 'ceph-for-6.9-rc1' of https://github.com/ceph/ceph-client:
ceph: set correct cap mask for getattr request for read
ceph: stop copying to iter at EOF on sync reads
ceph: remove SLAB_MEM_SPREAD flag usage
ceph: break the check delayed cap loop every 5s
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/caps.c | 8 | ||||
-rw-r--r-- | fs/ceph/file.c | 31 |
2 files changed, 26 insertions, 13 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 7fb4aae97412..55051ad09c19 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -4634,6 +4634,14 @@ unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc) iput(inode); spin_lock(&mdsc->cap_delay_lock); } + + /* + * Make sure too many dirty caps or general + * slowness doesn't block mdsc delayed work, + * preventing send_renew_caps() from running. + */ + if (jiffies - loop_start >= 5 * HZ) + break; } spin_unlock(&mdsc->cap_delay_lock); doutc(cl, "done\n"); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index abe8028d95bf..16873d07692f 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1138,7 +1138,12 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos, } idx = 0; - left = ret > 0 ? ret : 0; + if (ret <= 0) + left = 0; + else if (off + ret > i_size) + left = i_size - off; + else + left = ret; while (left > 0) { size_t plen, copied; @@ -1167,15 +1172,13 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos, } if (ret > 0) { - if (off > *ki_pos) { - if (off >= i_size) { - *retry_op = CHECK_EOF; - ret = i_size - *ki_pos; - *ki_pos = i_size; - } else { - ret = off - *ki_pos; - *ki_pos = off; - } + if (off >= i_size) { + *retry_op = CHECK_EOF; + ret = i_size - *ki_pos; + *ki_pos = i_size; + } else { + ret = off - *ki_pos; + *ki_pos = off; } if (last_objver) @@ -2126,14 +2129,16 @@ again: int statret; struct page *page = NULL; loff_t i_size; + int mask = CEPH_STAT_CAP_SIZE; if (retry_op == READ_INLINE) { page = __page_cache_alloc(GFP_KERNEL); if (!page) return -ENOMEM; + + mask = CEPH_STAT_CAP_INLINE_DATA; } - statret = __ceph_do_getattr(inode, page, - CEPH_STAT_CAP_INLINE_DATA, !!page); + statret = __ceph_do_getattr(inode, page, mask, !!page); if (statret < 0) { if (page) __free_page(page); @@ -2174,7 +2179,7 @@ again: /* hit EOF or hole? */ if (retry_op == CHECK_EOF && iocb->ki_pos < i_size && ret < len) { - doutc(cl, "hit hole, ppos %lld < size %lld, reading more\n", + doutc(cl, "may hit hole, ppos %lld < size %lld, reading more\n", iocb->ki_pos, i_size); read += ret; |