On Tue, Feb 28, 2012 at 7:21 PM, Alex Elder <elder@xxxxxxxxxxxxx> wrote: > All names defined in the directory and file virtual extended > attribute tables are constant, and the size of each is known at > compile time. So there's no need to compute their length every > time any file's attribute is listed. > > Record the length of each string and use it when needed to determine > the space need to represent them. In addition, compute the > aggregate size of strings in each table just once at initialization > time. > > Signed-off-by: Alex Elder <elder@xxxxxxxxxxxxx> > --- > fs/ceph/super.c | 3 ++ > fs/ceph/super.h | 2 + > fs/ceph/xattr.c | 56 > ++++++++++++++++++++++++++++++++++++++++++++++++++---- > 3 files changed, 56 insertions(+), 5 deletions(-) > > diff --git a/fs/ceph/super.c b/fs/ceph/super.c > index b48f15f..e6325f0 100644 > --- a/fs/ceph/super.c > +++ b/fs/ceph/super.c > @@ -906,6 +906,7 @@ static int __init init_ceph(void) > if (ret) > goto out; > > + ceph_xattr_init(); > ret = register_filesystem(&ceph_fs_type); > if (ret) > goto out_icache; > @@ -915,6 +916,7 @@ static int __init init_ceph(void) > return 0; > > out_icache: > + ceph_xattr_exit(); > destroy_caches(); > out: > return ret; > @@ -924,6 +926,7 @@ static void __exit exit_ceph(void) > { > dout("exit_ceph\n"); > unregister_filesystem(&ceph_fs_type); > + ceph_xattr_exit(); > destroy_caches(); > } > > diff --git a/fs/ceph/super.h b/fs/ceph/super.h > index 5f00e82..4be2dc4 100644 > --- a/fs/ceph/super.h > +++ b/fs/ceph/super.h > @@ -732,6 +732,8 @@ extern ssize_t ceph_listxattr(struct dentry *, char *, > size_t); > extern int ceph_removexattr(struct dentry *, const char *); > extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci); > extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci); > +extern void __init ceph_xattr_init(void); > +extern void ceph_xattr_exit(void); > > /* caps.c */ > extern const char *ceph_cap_string(int c); > diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c > index 83366f9..984c863 100644 > --- a/fs/ceph/xattr.c > +++ b/fs/ceph/xattr.c > @@ -26,6 +26,7 @@ static bool ceph_is_valid_xattr(const char *name) > */ > struct ceph_vxattr { > char *name; > + size_t name_size; /* strlen(name) + 1 (for '\0') */ > size_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val, > size_t size); > bool readonly; > @@ -87,6 +88,7 @@ static size_t ceph_vxattrcb_dir_rctime(struct > ceph_inode_info *ci, char *val, > #define XATTR_NAME_CEPH(_type, _name) \ > { \ > .name = CEPH_XATTR_NAME(_type, _name), \ > + .name_size = sizeof CEPH_XATTR_NAME(_type, _name), \ You should use sizeof(x) instead of sizeof x. > .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, > \ > .readonly = true, \ > } > @@ -102,6 +104,7 @@ static struct ceph_vxattr ceph_dir_vxattrs[] = { > XATTR_NAME_CEPH(dir, rctime), > { 0 } /* Required table terminator */ > }; > +static size_t ceph_dir_vxattrs_name_size; /* total size of all names > */ > > /* files */ > > @@ -127,11 +130,13 @@ static struct ceph_vxattr ceph_file_vxattrs[] = { > /* The following extended attribute name is deprecated */ > { > .name = XATTR_CEPH_PREFIX "layout", > + .name_size = sizeof XATTR_CEPH_PREFIX "layout", here too. > .getxattr_cb = ceph_vxattrcb_file_layout, > .readonly = true, > }, > { 0 } /* Required table terminator */ > }; > +static size_t ceph_file_vxattrs_name_size; /* total size of all names > */ > > static struct ceph_vxattr *ceph_inode_vxattrs(struct inode *inode) > { > @@ -142,6 +147,46 @@ static struct ceph_vxattr *ceph_inode_vxattrs(struct > inode *inode) > return NULL; > } > > +static size_t ceph_vxattrs_name_size(struct ceph_vxattr *vxattrs) > +{ > + if (vxattrs == ceph_dir_vxattrs) > + return ceph_dir_vxattrs_name_size; > + if (vxattrs == ceph_file_vxattrs) > + return ceph_file_vxattrs_name_size; > + BUG(); > + > + return 0; > +} > + > +/* > + * Compute the aggregate size (including terminating '\0') of all > + * virtual extended attribute names in the given vxattr table. > + */ > +static size_t __init vxattrs_name_size(struct ceph_vxattr *vxattrs) > +{sizeof > + struct ceph_vxattr *vxattr; > + size_t size = 0; > + > + for (vxattr = vxattrs; vxattr->name; vxattr++) > + size += vxattr->name_size; > + > + return size; > +} > + > +/* Routines called at initialization and exit time */ > + > +void __init ceph_xattr_init(void) > +{ > + ceph_dir_vxattrs_name_size = vxattrs_name_size(ceph_dir_vxattrs); > + ceph_file_vxattrs_name_size = vxattrs_name_size(ceph_file_vxattrs); > +} > + > +void ceph_xattr_exit(void) > +{ > + ceph_dir_vxattrs_name_size = 0; > + ceph_file_vxattrs_name_size = 0; > +} > + > static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode, > const char *name) > { > @@ -614,11 +659,12 @@ ssize_t ceph_listxattr(struct dentry *dentry, char > *names, size_t size) > goto out; > > list_xattr: > - vir_namelen = 0; > - /* include virtual dir xattrs */ > - if (vxattrs) > - for (i = 0; vxattrs[i].name; i++) > - vir_namelen += strlen(vxattrs[i].name) + 1; > + /* > + * Start with virtual dir xattr names (if any) (including > + * terminating '\0' characters for each). > + */ > + vir_namelen = ceph_vxattrs_name_size(vxattrs); > + > /* adding 1 byte per each variable due to the null termination */ > namelen = vir_namelen + ci->i_xattrs.names_size + ci->i_xattrs.count; > err = -ERANGE; > -- > 1.7.5.4 > > -- > To unsubscribe from this list: send the line "unsubscribe ceph-devel" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe ceph-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html