Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ceph: avoid repeatedly computing the size of constant vxattr names

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@dreamhost.com>
Signed-off-by: Sage Weil <sage@newdream.net>

+56 -5
+3
fs/ceph/super.c
··· 927 927 if (ret) 928 928 goto out; 929 929 930 + ceph_xattr_init(); 930 931 ret = register_filesystem(&ceph_fs_type); 931 932 if (ret) 932 933 goto out_icache; ··· 937 936 return 0; 938 937 939 938 out_icache: 939 + ceph_xattr_exit(); 940 940 destroy_caches(); 941 941 out: 942 942 return ret; ··· 947 945 { 948 946 dout("exit_ceph\n"); 949 947 unregister_filesystem(&ceph_fs_type); 948 + ceph_xattr_exit(); 950 949 destroy_caches(); 951 950 } 952 951
+2
fs/ceph/super.h
··· 733 733 extern int ceph_removexattr(struct dentry *, const char *); 734 734 extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci); 735 735 extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci); 736 + extern void __init ceph_xattr_init(void); 737 + extern void ceph_xattr_exit(void); 736 738 737 739 /* caps.c */ 738 740 extern const char *ceph_cap_string(int c);
+51 -5
fs/ceph/xattr.c
··· 26 26 */ 27 27 struct ceph_vxattr { 28 28 char *name; 29 + size_t name_size; /* strlen(name) + 1 (for '\0') */ 29 30 size_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val, 30 31 size_t size); 31 32 bool readonly; ··· 88 87 #define XATTR_NAME_CEPH(_type, _name) \ 89 88 { \ 90 89 .name = CEPH_XATTR_NAME(_type, _name), \ 90 + .name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \ 91 91 .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \ 92 92 .readonly = true, \ 93 93 } ··· 104 102 XATTR_NAME_CEPH(dir, rctime), 105 103 { 0 } /* Required table terminator */ 106 104 }; 105 + static size_t ceph_dir_vxattrs_name_size; /* total size of all names */ 107 106 108 107 /* files */ 109 108 ··· 130 127 /* The following extended attribute name is deprecated */ 131 128 { 132 129 .name = XATTR_CEPH_PREFIX "layout", 130 + .name_size = sizeof (XATTR_CEPH_PREFIX "layout"), 133 131 .getxattr_cb = ceph_vxattrcb_file_layout, 134 132 .readonly = true, 135 133 }, 136 134 { 0 } /* Required table terminator */ 137 135 }; 136 + static size_t ceph_file_vxattrs_name_size; /* total size of all names */ 138 137 139 138 static struct ceph_vxattr *ceph_inode_vxattrs(struct inode *inode) 140 139 { ··· 145 140 else if (S_ISREG(inode->i_mode)) 146 141 return ceph_file_vxattrs; 147 142 return NULL; 143 + } 144 + 145 + static size_t ceph_vxattrs_name_size(struct ceph_vxattr *vxattrs) 146 + { 147 + if (vxattrs == ceph_dir_vxattrs) 148 + return ceph_dir_vxattrs_name_size; 149 + if (vxattrs == ceph_file_vxattrs) 150 + return ceph_file_vxattrs_name_size; 151 + BUG(); 152 + 153 + return 0; 154 + } 155 + 156 + /* 157 + * Compute the aggregate size (including terminating '\0') of all 158 + * virtual extended attribute names in the given vxattr table. 159 + */ 160 + static size_t __init vxattrs_name_size(struct ceph_vxattr *vxattrs) 161 + { 162 + struct ceph_vxattr *vxattr; 163 + size_t size = 0; 164 + 165 + for (vxattr = vxattrs; vxattr->name; vxattr++) 166 + size += vxattr->name_size; 167 + 168 + return size; 169 + } 170 + 171 + /* Routines called at initialization and exit time */ 172 + 173 + void __init ceph_xattr_init(void) 174 + { 175 + ceph_dir_vxattrs_name_size = vxattrs_name_size(ceph_dir_vxattrs); 176 + ceph_file_vxattrs_name_size = vxattrs_name_size(ceph_file_vxattrs); 177 + } 178 + 179 + void ceph_xattr_exit(void) 180 + { 181 + ceph_dir_vxattrs_name_size = 0; 182 + ceph_file_vxattrs_name_size = 0; 148 183 } 149 184 150 185 static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode, ··· 660 615 goto out; 661 616 662 617 list_xattr: 663 - vir_namelen = 0; 664 - /* include virtual dir xattrs */ 665 - if (vxattrs) 666 - for (i = 0; vxattrs[i].name; i++) 667 - vir_namelen += strlen(vxattrs[i].name) + 1; 618 + /* 619 + * Start with virtual dir xattr names (if any) (including 620 + * terminating '\0' characters for each). 621 + */ 622 + vir_namelen = ceph_vxattrs_name_size(vxattrs); 623 + 668 624 /* adding 1 byte per each variable due to the null termination */ 669 625 namelen = vir_namelen + ci->i_xattrs.names_size + ci->i_xattrs.count; 670 626 err = -ERANGE;