| From 620239d9a32e9fe27c9204ec11e40058671aeeb6 Mon Sep 17 00:00:00 2001 |
| From: Jeff Layton <jlayton@kernel.org> |
| Date: Mon, 25 Apr 2022 15:54:27 -0400 |
| Subject: ceph: fix setting of xattrs on async created inodes |
| |
| From: Jeff Layton <jlayton@kernel.org> |
| |
| commit 620239d9a32e9fe27c9204ec11e40058671aeeb6 upstream. |
| |
| Currently when we create a file, we spin up an xattr buffer to send |
| along with the create request. If we end up doing an async create |
| however, then we currently pass down a zero-length xattr buffer. |
| |
| Fix the code to send down the xattr buffer in req->r_pagelist. If the |
| xattrs span more than a page, however give up and don't try to do an |
| async create. |
| |
| Cc: stable@vger.kernel.org |
| URL: https://bugzilla.redhat.com/show_bug.cgi?id=2063929 |
| Fixes: 9a8d03ca2e2c ("ceph: attempt to do async create when possible") |
| Reported-by: John Fortin <fortinj66@gmail.com> |
| Reported-by: Sri Ramanujam <sri@ramanujam.io> |
| Signed-off-by: Jeff Layton <jlayton@kernel.org> |
| Reviewed-by: Xiubo Li <xiubli@redhat.com> |
| Signed-off-by: Ilya Dryomov <idryomov@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/ceph/file.c | 16 +++++++++++++--- |
| 1 file changed, 13 insertions(+), 3 deletions(-) |
| |
| --- a/fs/ceph/file.c |
| +++ b/fs/ceph/file.c |
| @@ -598,9 +598,15 @@ static int ceph_finish_async_create(stru |
| iinfo.change_attr = 1; |
| ceph_encode_timespec64(&iinfo.btime, &now); |
| |
| - iinfo.xattr_len = ARRAY_SIZE(xattr_buf); |
| - iinfo.xattr_data = xattr_buf; |
| - memset(iinfo.xattr_data, 0, iinfo.xattr_len); |
| + if (req->r_pagelist) { |
| + iinfo.xattr_len = req->r_pagelist->length; |
| + iinfo.xattr_data = req->r_pagelist->mapped_tail; |
| + } else { |
| + /* fake it */ |
| + iinfo.xattr_len = ARRAY_SIZE(xattr_buf); |
| + iinfo.xattr_data = xattr_buf; |
| + memset(iinfo.xattr_data, 0, iinfo.xattr_len); |
| + } |
| |
| in.ino = cpu_to_le64(vino.ino); |
| in.snapid = cpu_to_le64(CEPH_NOSNAP); |
| @@ -712,6 +718,10 @@ int ceph_atomic_open(struct inode *dir, |
| err = ceph_security_init_secctx(dentry, mode, &as_ctx); |
| if (err < 0) |
| goto out_ctx; |
| + /* Async create can't handle more than a page of xattrs */ |
| + if (as_ctx.pagelist && |
| + !list_is_singular(&as_ctx.pagelist->head)) |
| + try_async = false; |
| } else if (!d_in_lookup(dentry)) { |
| /* If it's not being looked up, it's negative */ |
| return -ENOENT; |