* [PATCH v2 0/2] ceph: support cross-quota-tree renames
@ 2020-04-07 10:30 Luis Henriques
2020-04-07 10:30 ` [PATCH v2 1/2] ceph: normalize 'delta' parameter usage in check_quota_exceeded Luis Henriques
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Luis Henriques @ 2020-04-07 10:30 UTC (permalink / raw)
To: Jeff Layton, Sage Weil, Ilya Dryomov, Gregory Farnum, Zheng Yan
Cc: Frank Schilder, ceph-devel, linux-kernel, Luis Henriques
Hi!
The following patches will make the cephfs kernel client behave the same
way as the fuse client when doing renames across different quota realms.
Changes since v1:
- Dropped 'old == new' check in ceph_quota_check_rename() and added back
optimization in ceph_rename(), to only check realms if old_dir and
new_dir are different.
Luis Henriques (2):
ceph: normalize 'delta' parameter usage in check_quota_exceeded
ceph: allow rename operation under different quota realms
fs/ceph/dir.c | 9 +++----
fs/ceph/quota.c | 62 +++++++++++++++++++++++++++++++++++++++++++++----
fs/ceph/super.h | 3 ++-
3 files changed, 65 insertions(+), 9 deletions(-)
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2 1/2] ceph: normalize 'delta' parameter usage in check_quota_exceeded 2020-04-07 10:30 [PATCH v2 0/2] ceph: support cross-quota-tree renames Luis Henriques @ 2020-04-07 10:30 ` Luis Henriques 2020-04-07 10:30 ` [PATCH v2 2/2] ceph: allow rename operation under different quota realms Luis Henriques 2020-04-08 14:31 ` [PATCH v2 0/2] ceph: support cross-quota-tree renames Jeff Layton 2 siblings, 0 replies; 6+ messages in thread From: Luis Henriques @ 2020-04-07 10:30 UTC (permalink / raw) To: Jeff Layton, Sage Weil, Ilya Dryomov, Gregory Farnum, Zheng Yan Cc: Frank Schilder, ceph-devel, linux-kernel, Luis Henriques Function check_quota_exceeded() uses delta parameter only for the QUOTA_CHECK_MAX_BYTES_OP operation. Using this parameter also for MAX_FILES will makes the code cleaner and will be required to support cross-quota-tree renames. Signed-off-by: Luis Henriques <lhenriques@suse.com> --- fs/ceph/quota.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c index de56dee60540..c5c8050f0f99 100644 --- a/fs/ceph/quota.c +++ b/fs/ceph/quota.c @@ -361,8 +361,6 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op, spin_unlock(&ci->i_ceph_lock); switch (op) { case QUOTA_CHECK_MAX_FILES_OP: - exceeded = (max && (rvalue >= max)); - break; case QUOTA_CHECK_MAX_BYTES_OP: exceeded = (max && (rvalue + delta > max)); break; @@ -417,7 +415,7 @@ bool ceph_quota_is_max_files_exceeded(struct inode *inode) WARN_ON(!S_ISDIR(inode->i_mode)); - return check_quota_exceeded(inode, QUOTA_CHECK_MAX_FILES_OP, 0); + return check_quota_exceeded(inode, QUOTA_CHECK_MAX_FILES_OP, 1); } /* ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 2/2] ceph: allow rename operation under different quota realms 2020-04-07 10:30 [PATCH v2 0/2] ceph: support cross-quota-tree renames Luis Henriques 2020-04-07 10:30 ` [PATCH v2 1/2] ceph: normalize 'delta' parameter usage in check_quota_exceeded Luis Henriques @ 2020-04-07 10:30 ` Luis Henriques 2020-04-07 22:57 ` Jeff Layton 2020-04-08 14:31 ` [PATCH v2 0/2] ceph: support cross-quota-tree renames Jeff Layton 2 siblings, 1 reply; 6+ messages in thread From: Luis Henriques @ 2020-04-07 10:30 UTC (permalink / raw) To: Jeff Layton, Sage Weil, Ilya Dryomov, Gregory Farnum, Zheng Yan Cc: Frank Schilder, ceph-devel, linux-kernel, Luis Henriques Returning -EXDEV when trying to 'mv' files/directories from different quota realms results in copy+unlink operations instead of the faster CEPH_MDS_OP_RENAME. This will occur even when there aren't any quotas set in the destination directory, or if there's enough space left for the new file(s). This patch adds a new helper function to be called on rename operations which will allow these operations if they can be executed. This patch mimics userland fuse client commit b8954e5734b3 ("client: optimize rename operation under different quota root"). Since ceph_quota_is_same_realm() is now called only from this new helper, make it static. URL: https://tracker.ceph.com/issues/44791 Signed-off-by: Luis Henriques <lhenriques@suse.com> --- fs/ceph/dir.c | 9 ++++---- fs/ceph/quota.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++- fs/ceph/super.h | 3 ++- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index d0cd0aba5843..23f0345611a3 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1099,11 +1099,12 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry, op = CEPH_MDS_OP_RENAMESNAP; else return -EROFS; + } else if (old_dir != new_dir) { + err = ceph_quota_check_rename(mdsc, d_inode(old_dentry), + new_dir); + if (err) + return err; } - /* don't allow cross-quota renames */ - if ((old_dir != new_dir) && - (!ceph_quota_is_same_realm(old_dir, new_dir))) - return -EXDEV; dout("rename dir %p dentry %p to dir %p dentry %p\n", old_dir, old_dentry, new_dir, new_dentry); diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c index c5c8050f0f99..9e82704a9f7b 100644 --- a/fs/ceph/quota.c +++ b/fs/ceph/quota.c @@ -264,7 +264,7 @@ static struct ceph_snap_realm *get_quota_realm(struct ceph_mds_client *mdsc, return NULL; } -bool ceph_quota_is_same_realm(struct inode *old, struct inode *new) +static bool ceph_quota_is_same_realm(struct inode *old, struct inode *new) { struct ceph_mds_client *mdsc = ceph_inode_to_client(old)->mdsc; struct ceph_snap_realm *old_realm, *new_realm; @@ -516,3 +516,59 @@ bool ceph_quota_update_statfs(struct ceph_fs_client *fsc, struct kstatfs *buf) return is_updated; } +/* + * ceph_quota_check_rename - check if a rename can be executed + * @mdsc: MDS client instance + * @old: inode to be copied + * @new: destination inode (directory) + * + * This function verifies if a rename (e.g. moving a file or directory) can be + * executed. It forces an rstat update in the @new target directory (and in the + * source @old as well, if it's a directory). The actual check is done both for + * max_files and max_bytes. + * + * This function returns 0 if it's OK to do the rename, or, if quotas are + * exceeded, -EXDEV (if @old is a directory) or -EDQUOT. + */ +int ceph_quota_check_rename(struct ceph_mds_client *mdsc, + struct inode *old, struct inode *new) +{ + struct ceph_inode_info *ci_old = ceph_inode(old); + int ret = 0; + + if (ceph_quota_is_same_realm(old, new)) + return 0; + + /* + * Get the latest rstat for target directory (and for source, if a + * directory) + */ + ret = ceph_do_getattr(new, CEPH_STAT_RSTAT, false); + if (ret) + return ret; + + if (S_ISDIR(old->i_mode)) { + ret = ceph_do_getattr(old, CEPH_STAT_RSTAT, false); + if (ret) + return ret; + ret = check_quota_exceeded(new, QUOTA_CHECK_MAX_BYTES_OP, + ci_old->i_rbytes); + if (!ret) + ret = check_quota_exceeded(new, + QUOTA_CHECK_MAX_FILES_OP, + ci_old->i_rfiles + + ci_old->i_rsubdirs); + if (ret) + ret = -EXDEV; + } else { + ret = check_quota_exceeded(new, QUOTA_CHECK_MAX_BYTES_OP, + i_size_read(old)); + if (!ret) + ret = check_quota_exceeded(new, + QUOTA_CHECK_MAX_FILES_OP, 1); + if (ret) + ret = -EDQUOT; + } + + return ret; +} diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 037cdfb2ad4f..d5853831a6b5 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -1175,13 +1175,14 @@ extern void ceph_handle_quota(struct ceph_mds_client *mdsc, struct ceph_mds_session *session, struct ceph_msg *msg); extern bool ceph_quota_is_max_files_exceeded(struct inode *inode); -extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new); extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, loff_t newlen); extern bool ceph_quota_is_max_bytes_approaching(struct inode *inode, loff_t newlen); extern bool ceph_quota_update_statfs(struct ceph_fs_client *fsc, struct kstatfs *buf); +extern int ceph_quota_check_rename(struct ceph_mds_client *mdsc, + struct inode *old, struct inode *new); extern void ceph_cleanup_quotarealms_inodes(struct ceph_mds_client *mdsc); #endif /* _FS_CEPH_SUPER_H */ ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] ceph: allow rename operation under different quota realms 2020-04-07 10:30 ` [PATCH v2 2/2] ceph: allow rename operation under different quota realms Luis Henriques @ 2020-04-07 22:57 ` Jeff Layton 2020-04-08 3:10 ` Yan, Zheng 0 siblings, 1 reply; 6+ messages in thread From: Jeff Layton @ 2020-04-07 22:57 UTC (permalink / raw) To: Luis Henriques, Sage Weil, Ilya Dryomov, Gregory Farnum, Zheng Yan Cc: Frank Schilder, ceph-devel, linux-kernel On Tue, 2020-04-07 at 11:30 +0100, Luis Henriques wrote: > Returning -EXDEV when trying to 'mv' files/directories from different > quota realms results in copy+unlink operations instead of the faster > CEPH_MDS_OP_RENAME. This will occur even when there aren't any quotas > set in the destination directory, or if there's enough space left for > the new file(s). > > This patch adds a new helper function to be called on rename operations > which will allow these operations if they can be executed. This patch > mimics userland fuse client commit b8954e5734b3 ("client: > optimize rename operation under different quota root"). > > Since ceph_quota_is_same_realm() is now called only from this new > helper, make it static. > > URL: https://tracker.ceph.com/issues/44791 > Signed-off-by: Luis Henriques <lhenriques@suse.com> > --- > fs/ceph/dir.c | 9 ++++---- > fs/ceph/quota.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++- > fs/ceph/super.h | 3 ++- > 3 files changed, 64 insertions(+), 6 deletions(-) > > diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c > index d0cd0aba5843..23f0345611a3 100644 > --- a/fs/ceph/dir.c > +++ b/fs/ceph/dir.c > @@ -1099,11 +1099,12 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry, > op = CEPH_MDS_OP_RENAMESNAP; > else > return -EROFS; > + } else if (old_dir != new_dir) { > + err = ceph_quota_check_rename(mdsc, d_inode(old_dentry), > + new_dir); > + if (err) > + return err; > } > - /* don't allow cross-quota renames */ > - if ((old_dir != new_dir) && > - (!ceph_quota_is_same_realm(old_dir, new_dir))) > - return -EXDEV; > > dout("rename dir %p dentry %p to dir %p dentry %p\n", > old_dir, old_dentry, new_dir, new_dentry); > diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c > index c5c8050f0f99..9e82704a9f7b 100644 > --- a/fs/ceph/quota.c > +++ b/fs/ceph/quota.c > @@ -264,7 +264,7 @@ static struct ceph_snap_realm *get_quota_realm(struct ceph_mds_client *mdsc, > return NULL; > } > > -bool ceph_quota_is_same_realm(struct inode *old, struct inode *new) > +static bool ceph_quota_is_same_realm(struct inode *old, struct inode *new) > { > struct ceph_mds_client *mdsc = ceph_inode_to_client(old)->mdsc; > struct ceph_snap_realm *old_realm, *new_realm; > @@ -516,3 +516,59 @@ bool ceph_quota_update_statfs(struct ceph_fs_client *fsc, struct kstatfs *buf) > return is_updated; > } > > +/* > + * ceph_quota_check_rename - check if a rename can be executed > + * @mdsc: MDS client instance > + * @old: inode to be copied > + * @new: destination inode (directory) > + * > + * This function verifies if a rename (e.g. moving a file or directory) can be > + * executed. It forces an rstat update in the @new target directory (and in the > + * source @old as well, if it's a directory). The actual check is done both for > + * max_files and max_bytes. > + * > + * This function returns 0 if it's OK to do the rename, or, if quotas are > + * exceeded, -EXDEV (if @old is a directory) or -EDQUOT. > + */ > +int ceph_quota_check_rename(struct ceph_mds_client *mdsc, > + struct inode *old, struct inode *new) > +{ > + struct ceph_inode_info *ci_old = ceph_inode(old); > + int ret = 0; > + > + if (ceph_quota_is_same_realm(old, new)) > + return 0; > + > + /* > + * Get the latest rstat for target directory (and for source, if a > + * directory) > + */ > + ret = ceph_do_getattr(new, CEPH_STAT_RSTAT, false); > + if (ret) > + return ret; > + > + if (S_ISDIR(old->i_mode)) { > + ret = ceph_do_getattr(old, CEPH_STAT_RSTAT, false); > + if (ret) > + return ret; > + ret = check_quota_exceeded(new, QUOTA_CHECK_MAX_BYTES_OP, > + ci_old->i_rbytes); > + if (!ret) > + ret = check_quota_exceeded(new, > + QUOTA_CHECK_MAX_FILES_OP, > + ci_old->i_rfiles + > + ci_old->i_rsubdirs); Somewhat idle curiosity, but what happens with hardlinked files where one dentry is in one quota domain and another is in a different one? Does it stay in the old quotarealm? In any case, this is likely fine as non-hardlinked files are the pessimal case anyway. > + if (ret) > + ret = -EXDEV; > + } else { > + ret = check_quota_exceeded(new, QUOTA_CHECK_MAX_BYTES_OP, > + i_size_read(old)); > + if (!ret) > + ret = check_quota_exceeded(new, > + QUOTA_CHECK_MAX_FILES_OP, 1); > + if (ret) > + ret = -EDQUOT; > + } > + > + return ret; > +} > diff --git a/fs/ceph/super.h b/fs/ceph/super.h > index 037cdfb2ad4f..d5853831a6b5 100644 > --- a/fs/ceph/super.h > +++ b/fs/ceph/super.h > @@ -1175,13 +1175,14 @@ extern void ceph_handle_quota(struct ceph_mds_client *mdsc, > struct ceph_mds_session *session, > struct ceph_msg *msg); > extern bool ceph_quota_is_max_files_exceeded(struct inode *inode); > -extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new); > extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, > loff_t newlen); > extern bool ceph_quota_is_max_bytes_approaching(struct inode *inode, > loff_t newlen); > extern bool ceph_quota_update_statfs(struct ceph_fs_client *fsc, > struct kstatfs *buf); > +extern int ceph_quota_check_rename(struct ceph_mds_client *mdsc, > + struct inode *old, struct inode *new); > extern void ceph_cleanup_quotarealms_inodes(struct ceph_mds_client *mdsc); > > #endif /* _FS_CEPH_SUPER_H */ -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] ceph: allow rename operation under different quota realms 2020-04-07 22:57 ` Jeff Layton @ 2020-04-08 3:10 ` Yan, Zheng 0 siblings, 0 replies; 6+ messages in thread From: Yan, Zheng @ 2020-04-08 3:10 UTC (permalink / raw) To: Jeff Layton Cc: Luis Henriques, Sage Weil, Ilya Dryomov, Gregory Farnum, Zheng Yan, Frank Schilder, ceph-devel, Linux Kernel Mailing List On Wed, Apr 8, 2020 at 7:00 AM Jeff Layton <jlayton@kernel.org> wrote: > > Somewhat idle curiosity, but what happens with hardlinked files where > one dentry is in one quota domain and another is in a different one? > Does it stay in the old quotarealm? > > In any case, this is likely fine as non-hardlinked files are the > pessimal case anyway. rstat only tracks primary dentry. inode is in the quota realm where its primary linkage is in. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/2] ceph: support cross-quota-tree renames 2020-04-07 10:30 [PATCH v2 0/2] ceph: support cross-quota-tree renames Luis Henriques 2020-04-07 10:30 ` [PATCH v2 1/2] ceph: normalize 'delta' parameter usage in check_quota_exceeded Luis Henriques 2020-04-07 10:30 ` [PATCH v2 2/2] ceph: allow rename operation under different quota realms Luis Henriques @ 2020-04-08 14:31 ` Jeff Layton 2 siblings, 0 replies; 6+ messages in thread From: Jeff Layton @ 2020-04-08 14:31 UTC (permalink / raw) To: Luis Henriques, Sage Weil, Ilya Dryomov, Gregory Farnum, Zheng Yan Cc: Frank Schilder, ceph-devel, linux-kernel On Tue, 2020-04-07 at 11:30 +0100, Luis Henriques wrote: > Hi! > > The following patches will make the cephfs kernel client behave the same > way as the fuse client when doing renames across different quota realms. > > Changes since v1: > > - Dropped 'old == new' check in ceph_quota_check_rename() and added back > optimization in ceph_rename(), to only check realms if old_dir and > new_dir are different. > > Luis Henriques (2): > ceph: normalize 'delta' parameter usage in check_quota_exceeded > ceph: allow rename operation under different quota realms > > fs/ceph/dir.c | 9 +++---- > fs/ceph/quota.c | 62 +++++++++++++++++++++++++++++++++++++++++++++---- > fs/ceph/super.h | 3 ++- > 3 files changed, 65 insertions(+), 9 deletions(-) > Looks good. Merged into ceph-client/testing. Thanks! -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-04-08 14:31 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-04-07 10:30 [PATCH v2 0/2] ceph: support cross-quota-tree renames Luis Henriques 2020-04-07 10:30 ` [PATCH v2 1/2] ceph: normalize 'delta' parameter usage in check_quota_exceeded Luis Henriques 2020-04-07 10:30 ` [PATCH v2 2/2] ceph: allow rename operation under different quota realms Luis Henriques 2020-04-07 22:57 ` Jeff Layton 2020-04-08 3:10 ` Yan, Zheng 2020-04-08 14:31 ` [PATCH v2 0/2] ceph: support cross-quota-tree renames Jeff Layton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®