Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/ceph/ceph_debug.h>
0003 #include <linux/ceph/pagelist.h>
0004 
0005 #include "super.h"
0006 #include "mds_client.h"
0007 
0008 #include <linux/ceph/decode.h>
0009 
0010 #include <linux/xattr.h>
0011 #include <linux/security.h>
0012 #include <linux/posix_acl_xattr.h>
0013 #include <linux/slab.h>
0014 
0015 #define XATTR_CEPH_PREFIX "ceph."
0016 #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1)
0017 
0018 static int __remove_xattr(struct ceph_inode_info *ci,
0019               struct ceph_inode_xattr *xattr);
0020 
0021 static bool ceph_is_valid_xattr(const char *name)
0022 {
0023     return !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
0024            !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) ||
0025            !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
0026            !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
0027 }
0028 
0029 /*
0030  * These define virtual xattrs exposing the recursive directory
0031  * statistics and layout metadata.
0032  */
0033 struct ceph_vxattr {
0034     char *name;
0035     size_t name_size;   /* strlen(name) + 1 (for '\0') */
0036     ssize_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val,
0037                    size_t size);
0038     bool (*exists_cb)(struct ceph_inode_info *ci);
0039     unsigned int flags;
0040 };
0041 
0042 #define VXATTR_FLAG_READONLY        (1<<0)
0043 #define VXATTR_FLAG_HIDDEN      (1<<1)
0044 #define VXATTR_FLAG_RSTAT       (1<<2)
0045 #define VXATTR_FLAG_DIRSTAT     (1<<3)
0046 
0047 /* layouts */
0048 
0049 static bool ceph_vxattrcb_layout_exists(struct ceph_inode_info *ci)
0050 {
0051     struct ceph_file_layout *fl = &ci->i_layout;
0052     return (fl->stripe_unit > 0 || fl->stripe_count > 0 ||
0053         fl->object_size > 0 || fl->pool_id >= 0 ||
0054         rcu_dereference_raw(fl->pool_ns) != NULL);
0055 }
0056 
0057 static ssize_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
0058                     size_t size)
0059 {
0060     struct ceph_fs_client *fsc = ceph_sb_to_client(ci->netfs.inode.i_sb);
0061     struct ceph_osd_client *osdc = &fsc->client->osdc;
0062     struct ceph_string *pool_ns;
0063     s64 pool = ci->i_layout.pool_id;
0064     const char *pool_name;
0065     const char *ns_field = " pool_namespace=";
0066     char buf[128];
0067     size_t len, total_len = 0;
0068     ssize_t ret;
0069 
0070     pool_ns = ceph_try_get_string(ci->i_layout.pool_ns);
0071 
0072     dout("ceph_vxattrcb_layout %p\n", &ci->netfs.inode);
0073     down_read(&osdc->lock);
0074     pool_name = ceph_pg_pool_name_by_id(osdc->osdmap, pool);
0075     if (pool_name) {
0076         len = snprintf(buf, sizeof(buf),
0077         "stripe_unit=%u stripe_count=%u object_size=%u pool=",
0078         ci->i_layout.stripe_unit, ci->i_layout.stripe_count,
0079             ci->i_layout.object_size);
0080         total_len = len + strlen(pool_name);
0081     } else {
0082         len = snprintf(buf, sizeof(buf),
0083         "stripe_unit=%u stripe_count=%u object_size=%u pool=%lld",
0084         ci->i_layout.stripe_unit, ci->i_layout.stripe_count,
0085         ci->i_layout.object_size, pool);
0086         total_len = len;
0087     }
0088 
0089     if (pool_ns)
0090         total_len += strlen(ns_field) + pool_ns->len;
0091 
0092     ret = total_len;
0093     if (size >= total_len) {
0094         memcpy(val, buf, len);
0095         ret = len;
0096         if (pool_name) {
0097             len = strlen(pool_name);
0098             memcpy(val + ret, pool_name, len);
0099             ret += len;
0100         }
0101         if (pool_ns) {
0102             len = strlen(ns_field);
0103             memcpy(val + ret, ns_field, len);
0104             ret += len;
0105             memcpy(val + ret, pool_ns->str, pool_ns->len);
0106             ret += pool_ns->len;
0107         }
0108     }
0109     up_read(&osdc->lock);
0110     ceph_put_string(pool_ns);
0111     return ret;
0112 }
0113 
0114 /*
0115  * The convention with strings in xattrs is that they should not be NULL
0116  * terminated, since we're returning the length with them. snprintf always
0117  * NULL terminates however, so call it on a temporary buffer and then memcpy
0118  * the result into place.
0119  */
0120 static __printf(3, 4)
0121 int ceph_fmt_xattr(char *val, size_t size, const char *fmt, ...)
0122 {
0123     int ret;
0124     va_list args;
0125     char buf[96]; /* NB: reevaluate size if new vxattrs are added */
0126 
0127     va_start(args, fmt);
0128     ret = vsnprintf(buf, size ? sizeof(buf) : 0, fmt, args);
0129     va_end(args);
0130 
0131     /* Sanity check */
0132     if (size && ret + 1 > sizeof(buf)) {
0133         WARN_ONCE(true, "Returned length too big (%d)", ret);
0134         return -E2BIG;
0135     }
0136 
0137     if (ret <= size)
0138         memcpy(val, buf, ret);
0139     return ret;
0140 }
0141 
0142 static ssize_t ceph_vxattrcb_layout_stripe_unit(struct ceph_inode_info *ci,
0143                         char *val, size_t size)
0144 {
0145     return ceph_fmt_xattr(val, size, "%u", ci->i_layout.stripe_unit);
0146 }
0147 
0148 static ssize_t ceph_vxattrcb_layout_stripe_count(struct ceph_inode_info *ci,
0149                          char *val, size_t size)
0150 {
0151     return ceph_fmt_xattr(val, size, "%u", ci->i_layout.stripe_count);
0152 }
0153 
0154 static ssize_t ceph_vxattrcb_layout_object_size(struct ceph_inode_info *ci,
0155                         char *val, size_t size)
0156 {
0157     return ceph_fmt_xattr(val, size, "%u", ci->i_layout.object_size);
0158 }
0159 
0160 static ssize_t ceph_vxattrcb_layout_pool(struct ceph_inode_info *ci,
0161                      char *val, size_t size)
0162 {
0163     ssize_t ret;
0164     struct ceph_fs_client *fsc = ceph_sb_to_client(ci->netfs.inode.i_sb);
0165     struct ceph_osd_client *osdc = &fsc->client->osdc;
0166     s64 pool = ci->i_layout.pool_id;
0167     const char *pool_name;
0168 
0169     down_read(&osdc->lock);
0170     pool_name = ceph_pg_pool_name_by_id(osdc->osdmap, pool);
0171     if (pool_name) {
0172         ret = strlen(pool_name);
0173         if (ret <= size)
0174             memcpy(val, pool_name, ret);
0175     } else {
0176         ret = ceph_fmt_xattr(val, size, "%lld", pool);
0177     }
0178     up_read(&osdc->lock);
0179     return ret;
0180 }
0181 
0182 static ssize_t ceph_vxattrcb_layout_pool_namespace(struct ceph_inode_info *ci,
0183                            char *val, size_t size)
0184 {
0185     ssize_t ret = 0;
0186     struct ceph_string *ns = ceph_try_get_string(ci->i_layout.pool_ns);
0187 
0188     if (ns) {
0189         ret = ns->len;
0190         if (ret <= size)
0191             memcpy(val, ns->str, ret);
0192         ceph_put_string(ns);
0193     }
0194     return ret;
0195 }
0196 
0197 /* directories */
0198 
0199 static ssize_t ceph_vxattrcb_dir_entries(struct ceph_inode_info *ci, char *val,
0200                      size_t size)
0201 {
0202     return ceph_fmt_xattr(val, size, "%lld", ci->i_files + ci->i_subdirs);
0203 }
0204 
0205 static ssize_t ceph_vxattrcb_dir_files(struct ceph_inode_info *ci, char *val,
0206                        size_t size)
0207 {
0208     return ceph_fmt_xattr(val, size, "%lld", ci->i_files);
0209 }
0210 
0211 static ssize_t ceph_vxattrcb_dir_subdirs(struct ceph_inode_info *ci, char *val,
0212                      size_t size)
0213 {
0214     return ceph_fmt_xattr(val, size, "%lld", ci->i_subdirs);
0215 }
0216 
0217 static ssize_t ceph_vxattrcb_dir_rentries(struct ceph_inode_info *ci, char *val,
0218                       size_t size)
0219 {
0220     return ceph_fmt_xattr(val, size, "%lld",
0221                 ci->i_rfiles + ci->i_rsubdirs);
0222 }
0223 
0224 static ssize_t ceph_vxattrcb_dir_rfiles(struct ceph_inode_info *ci, char *val,
0225                     size_t size)
0226 {
0227     return ceph_fmt_xattr(val, size, "%lld", ci->i_rfiles);
0228 }
0229 
0230 static ssize_t ceph_vxattrcb_dir_rsubdirs(struct ceph_inode_info *ci, char *val,
0231                       size_t size)
0232 {
0233     return ceph_fmt_xattr(val, size, "%lld", ci->i_rsubdirs);
0234 }
0235 
0236 static ssize_t ceph_vxattrcb_dir_rsnaps(struct ceph_inode_info *ci, char *val,
0237                       size_t size)
0238 {
0239     return ceph_fmt_xattr(val, size, "%lld", ci->i_rsnaps);
0240 }
0241 
0242 static ssize_t ceph_vxattrcb_dir_rbytes(struct ceph_inode_info *ci, char *val,
0243                     size_t size)
0244 {
0245     return ceph_fmt_xattr(val, size, "%lld", ci->i_rbytes);
0246 }
0247 
0248 static ssize_t ceph_vxattrcb_dir_rctime(struct ceph_inode_info *ci, char *val,
0249                     size_t size)
0250 {
0251     return ceph_fmt_xattr(val, size, "%lld.%09ld", ci->i_rctime.tv_sec,
0252                 ci->i_rctime.tv_nsec);
0253 }
0254 
0255 /* dir pin */
0256 static bool ceph_vxattrcb_dir_pin_exists(struct ceph_inode_info *ci)
0257 {
0258     return ci->i_dir_pin != -ENODATA;
0259 }
0260 
0261 static ssize_t ceph_vxattrcb_dir_pin(struct ceph_inode_info *ci, char *val,
0262                      size_t size)
0263 {
0264     return ceph_fmt_xattr(val, size, "%d", (int)ci->i_dir_pin);
0265 }
0266 
0267 /* quotas */
0268 static bool ceph_vxattrcb_quota_exists(struct ceph_inode_info *ci)
0269 {
0270     bool ret = false;
0271     spin_lock(&ci->i_ceph_lock);
0272     if ((ci->i_max_files || ci->i_max_bytes) &&
0273         ci->i_vino.snap == CEPH_NOSNAP &&
0274         ci->i_snap_realm &&
0275         ci->i_snap_realm->ino == ci->i_vino.ino)
0276         ret = true;
0277     spin_unlock(&ci->i_ceph_lock);
0278     return ret;
0279 }
0280 
0281 static ssize_t ceph_vxattrcb_quota(struct ceph_inode_info *ci, char *val,
0282                    size_t size)
0283 {
0284     return ceph_fmt_xattr(val, size, "max_bytes=%llu max_files=%llu",
0285                 ci->i_max_bytes, ci->i_max_files);
0286 }
0287 
0288 static ssize_t ceph_vxattrcb_quota_max_bytes(struct ceph_inode_info *ci,
0289                          char *val, size_t size)
0290 {
0291     return ceph_fmt_xattr(val, size, "%llu", ci->i_max_bytes);
0292 }
0293 
0294 static ssize_t ceph_vxattrcb_quota_max_files(struct ceph_inode_info *ci,
0295                          char *val, size_t size)
0296 {
0297     return ceph_fmt_xattr(val, size, "%llu", ci->i_max_files);
0298 }
0299 
0300 /* snapshots */
0301 static bool ceph_vxattrcb_snap_btime_exists(struct ceph_inode_info *ci)
0302 {
0303     return (ci->i_snap_btime.tv_sec != 0 || ci->i_snap_btime.tv_nsec != 0);
0304 }
0305 
0306 static ssize_t ceph_vxattrcb_snap_btime(struct ceph_inode_info *ci, char *val,
0307                     size_t size)
0308 {
0309     return ceph_fmt_xattr(val, size, "%lld.%09ld", ci->i_snap_btime.tv_sec,
0310                 ci->i_snap_btime.tv_nsec);
0311 }
0312 
0313 static ssize_t ceph_vxattrcb_cluster_fsid(struct ceph_inode_info *ci,
0314                       char *val, size_t size)
0315 {
0316     struct ceph_fs_client *fsc = ceph_sb_to_client(ci->netfs.inode.i_sb);
0317 
0318     return ceph_fmt_xattr(val, size, "%pU", &fsc->client->fsid);
0319 }
0320 
0321 static ssize_t ceph_vxattrcb_client_id(struct ceph_inode_info *ci,
0322                        char *val, size_t size)
0323 {
0324     struct ceph_fs_client *fsc = ceph_sb_to_client(ci->netfs.inode.i_sb);
0325 
0326     return ceph_fmt_xattr(val, size, "client%lld",
0327                   ceph_client_gid(fsc->client));
0328 }
0329 
0330 static ssize_t ceph_vxattrcb_caps(struct ceph_inode_info *ci, char *val,
0331                     size_t size)
0332 {
0333     int issued;
0334 
0335     spin_lock(&ci->i_ceph_lock);
0336     issued = __ceph_caps_issued(ci, NULL);
0337     spin_unlock(&ci->i_ceph_lock);
0338 
0339     return ceph_fmt_xattr(val, size, "%s/0x%x",
0340                   ceph_cap_string(issued), issued);
0341 }
0342 
0343 static ssize_t ceph_vxattrcb_auth_mds(struct ceph_inode_info *ci,
0344                        char *val, size_t size)
0345 {
0346     int ret;
0347 
0348     spin_lock(&ci->i_ceph_lock);
0349     ret = ceph_fmt_xattr(val, size, "%d",
0350                  ci->i_auth_cap ? ci->i_auth_cap->session->s_mds : -1);
0351     spin_unlock(&ci->i_ceph_lock);
0352     return ret;
0353 }
0354 
0355 #define CEPH_XATTR_NAME(_type, _name)   XATTR_CEPH_PREFIX #_type "." #_name
0356 #define CEPH_XATTR_NAME2(_type, _name, _name2)  \
0357     XATTR_CEPH_PREFIX #_type "." #_name "." #_name2
0358 
0359 #define XATTR_NAME_CEPH(_type, _name, _flags)               \
0360     {                               \
0361         .name = CEPH_XATTR_NAME(_type, _name),          \
0362         .name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \
0363         .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
0364         .exists_cb = NULL,                  \
0365         .flags = (VXATTR_FLAG_READONLY | _flags),       \
0366     }
0367 #define XATTR_RSTAT_FIELD(_type, _name)         \
0368     XATTR_NAME_CEPH(_type, _name, VXATTR_FLAG_RSTAT)
0369 #define XATTR_RSTAT_FIELD_UPDATABLE(_type, _name)           \
0370     {                               \
0371         .name = CEPH_XATTR_NAME(_type, _name),          \
0372         .name_size = sizeof (CEPH_XATTR_NAME(_type, _name)),    \
0373         .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name,   \
0374         .exists_cb = NULL,                  \
0375         .flags = VXATTR_FLAG_RSTAT,             \
0376     }
0377 #define XATTR_LAYOUT_FIELD(_type, _name, _field)            \
0378     {                               \
0379         .name = CEPH_XATTR_NAME2(_type, _name, _field), \
0380         .name_size = sizeof (CEPH_XATTR_NAME2(_type, _name, _field)), \
0381         .getxattr_cb = ceph_vxattrcb_ ## _name ## _ ## _field, \
0382         .exists_cb = ceph_vxattrcb_layout_exists,   \
0383         .flags = VXATTR_FLAG_HIDDEN,            \
0384     }
0385 #define XATTR_QUOTA_FIELD(_type, _name)                 \
0386     {                               \
0387         .name = CEPH_XATTR_NAME(_type, _name),          \
0388         .name_size = sizeof(CEPH_XATTR_NAME(_type, _name)), \
0389         .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name,   \
0390         .exists_cb = ceph_vxattrcb_quota_exists,        \
0391         .flags = VXATTR_FLAG_HIDDEN,                \
0392     }
0393 
0394 static struct ceph_vxattr ceph_dir_vxattrs[] = {
0395     {
0396         .name = "ceph.dir.layout",
0397         .name_size = sizeof("ceph.dir.layout"),
0398         .getxattr_cb = ceph_vxattrcb_layout,
0399         .exists_cb = ceph_vxattrcb_layout_exists,
0400         .flags = VXATTR_FLAG_HIDDEN,
0401     },
0402     XATTR_LAYOUT_FIELD(dir, layout, stripe_unit),
0403     XATTR_LAYOUT_FIELD(dir, layout, stripe_count),
0404     XATTR_LAYOUT_FIELD(dir, layout, object_size),
0405     XATTR_LAYOUT_FIELD(dir, layout, pool),
0406     XATTR_LAYOUT_FIELD(dir, layout, pool_namespace),
0407     XATTR_NAME_CEPH(dir, entries, VXATTR_FLAG_DIRSTAT),
0408     XATTR_NAME_CEPH(dir, files, VXATTR_FLAG_DIRSTAT),
0409     XATTR_NAME_CEPH(dir, subdirs, VXATTR_FLAG_DIRSTAT),
0410     XATTR_RSTAT_FIELD(dir, rentries),
0411     XATTR_RSTAT_FIELD(dir, rfiles),
0412     XATTR_RSTAT_FIELD(dir, rsubdirs),
0413     XATTR_RSTAT_FIELD(dir, rsnaps),
0414     XATTR_RSTAT_FIELD(dir, rbytes),
0415     XATTR_RSTAT_FIELD_UPDATABLE(dir, rctime),
0416     {
0417         .name = "ceph.dir.pin",
0418         .name_size = sizeof("ceph.dir.pin"),
0419         .getxattr_cb = ceph_vxattrcb_dir_pin,
0420         .exists_cb = ceph_vxattrcb_dir_pin_exists,
0421         .flags = VXATTR_FLAG_HIDDEN,
0422     },
0423     {
0424         .name = "ceph.quota",
0425         .name_size = sizeof("ceph.quota"),
0426         .getxattr_cb = ceph_vxattrcb_quota,
0427         .exists_cb = ceph_vxattrcb_quota_exists,
0428         .flags = VXATTR_FLAG_HIDDEN,
0429     },
0430     XATTR_QUOTA_FIELD(quota, max_bytes),
0431     XATTR_QUOTA_FIELD(quota, max_files),
0432     {
0433         .name = "ceph.snap.btime",
0434         .name_size = sizeof("ceph.snap.btime"),
0435         .getxattr_cb = ceph_vxattrcb_snap_btime,
0436         .exists_cb = ceph_vxattrcb_snap_btime_exists,
0437         .flags = VXATTR_FLAG_READONLY,
0438     },
0439     {
0440         .name = "ceph.caps",
0441         .name_size = sizeof("ceph.caps"),
0442         .getxattr_cb = ceph_vxattrcb_caps,
0443         .exists_cb = NULL,
0444         .flags = VXATTR_FLAG_HIDDEN,
0445     },
0446     { .name = NULL, 0 } /* Required table terminator */
0447 };
0448 
0449 /* files */
0450 
0451 static struct ceph_vxattr ceph_file_vxattrs[] = {
0452     {
0453         .name = "ceph.file.layout",
0454         .name_size = sizeof("ceph.file.layout"),
0455         .getxattr_cb = ceph_vxattrcb_layout,
0456         .exists_cb = ceph_vxattrcb_layout_exists,
0457         .flags = VXATTR_FLAG_HIDDEN,
0458     },
0459     XATTR_LAYOUT_FIELD(file, layout, stripe_unit),
0460     XATTR_LAYOUT_FIELD(file, layout, stripe_count),
0461     XATTR_LAYOUT_FIELD(file, layout, object_size),
0462     XATTR_LAYOUT_FIELD(file, layout, pool),
0463     XATTR_LAYOUT_FIELD(file, layout, pool_namespace),
0464     {
0465         .name = "ceph.snap.btime",
0466         .name_size = sizeof("ceph.snap.btime"),
0467         .getxattr_cb = ceph_vxattrcb_snap_btime,
0468         .exists_cb = ceph_vxattrcb_snap_btime_exists,
0469         .flags = VXATTR_FLAG_READONLY,
0470     },
0471     {
0472         .name = "ceph.caps",
0473         .name_size = sizeof("ceph.caps"),
0474         .getxattr_cb = ceph_vxattrcb_caps,
0475         .exists_cb = NULL,
0476         .flags = VXATTR_FLAG_HIDDEN,
0477     },
0478     { .name = NULL, 0 } /* Required table terminator */
0479 };
0480 
0481 static struct ceph_vxattr ceph_common_vxattrs[] = {
0482     {
0483         .name = "ceph.cluster_fsid",
0484         .name_size = sizeof("ceph.cluster_fsid"),
0485         .getxattr_cb = ceph_vxattrcb_cluster_fsid,
0486         .exists_cb = NULL,
0487         .flags = VXATTR_FLAG_READONLY,
0488     },
0489     {
0490         .name = "ceph.client_id",
0491         .name_size = sizeof("ceph.client_id"),
0492         .getxattr_cb = ceph_vxattrcb_client_id,
0493         .exists_cb = NULL,
0494         .flags = VXATTR_FLAG_READONLY,
0495     },
0496     {
0497         .name = "ceph.auth_mds",
0498         .name_size = sizeof("ceph.auth_mds"),
0499         .getxattr_cb = ceph_vxattrcb_auth_mds,
0500         .exists_cb = NULL,
0501         .flags = VXATTR_FLAG_READONLY,
0502     },
0503     { .name = NULL, 0 } /* Required table terminator */
0504 };
0505 
0506 static struct ceph_vxattr *ceph_inode_vxattrs(struct inode *inode)
0507 {
0508     if (S_ISDIR(inode->i_mode))
0509         return ceph_dir_vxattrs;
0510     else if (S_ISREG(inode->i_mode))
0511         return ceph_file_vxattrs;
0512     return NULL;
0513 }
0514 
0515 static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode,
0516                         const char *name)
0517 {
0518     struct ceph_vxattr *vxattr = ceph_inode_vxattrs(inode);
0519 
0520     if (vxattr) {
0521         while (vxattr->name) {
0522             if (!strcmp(vxattr->name, name))
0523                 return vxattr;
0524             vxattr++;
0525         }
0526     }
0527 
0528     vxattr = ceph_common_vxattrs;
0529     while (vxattr->name) {
0530         if (!strcmp(vxattr->name, name))
0531             return vxattr;
0532         vxattr++;
0533     }
0534 
0535     return NULL;
0536 }
0537 
0538 static int __set_xattr(struct ceph_inode_info *ci,
0539                const char *name, int name_len,
0540                const char *val, int val_len,
0541                int flags, int update_xattr,
0542                struct ceph_inode_xattr **newxattr)
0543 {
0544     struct rb_node **p;
0545     struct rb_node *parent = NULL;
0546     struct ceph_inode_xattr *xattr = NULL;
0547     int c;
0548     int new = 0;
0549 
0550     p = &ci->i_xattrs.index.rb_node;
0551     while (*p) {
0552         parent = *p;
0553         xattr = rb_entry(parent, struct ceph_inode_xattr, node);
0554         c = strncmp(name, xattr->name, min(name_len, xattr->name_len));
0555         if (c < 0)
0556             p = &(*p)->rb_left;
0557         else if (c > 0)
0558             p = &(*p)->rb_right;
0559         else {
0560             if (name_len == xattr->name_len)
0561                 break;
0562             else if (name_len < xattr->name_len)
0563                 p = &(*p)->rb_left;
0564             else
0565                 p = &(*p)->rb_right;
0566         }
0567         xattr = NULL;
0568     }
0569 
0570     if (update_xattr) {
0571         int err = 0;
0572 
0573         if (xattr && (flags & XATTR_CREATE))
0574             err = -EEXIST;
0575         else if (!xattr && (flags & XATTR_REPLACE))
0576             err = -ENODATA;
0577         if (err) {
0578             kfree(name);
0579             kfree(val);
0580             kfree(*newxattr);
0581             return err;
0582         }
0583         if (update_xattr < 0) {
0584             if (xattr)
0585                 __remove_xattr(ci, xattr);
0586             kfree(name);
0587             kfree(*newxattr);
0588             return 0;
0589         }
0590     }
0591 
0592     if (!xattr) {
0593         new = 1;
0594         xattr = *newxattr;
0595         xattr->name = name;
0596         xattr->name_len = name_len;
0597         xattr->should_free_name = update_xattr;
0598 
0599         ci->i_xattrs.count++;
0600         dout("__set_xattr count=%d\n", ci->i_xattrs.count);
0601     } else {
0602         kfree(*newxattr);
0603         *newxattr = NULL;
0604         if (xattr->should_free_val)
0605             kfree(xattr->val);
0606 
0607         if (update_xattr) {
0608             kfree(name);
0609             name = xattr->name;
0610         }
0611         ci->i_xattrs.names_size -= xattr->name_len;
0612         ci->i_xattrs.vals_size -= xattr->val_len;
0613     }
0614     ci->i_xattrs.names_size += name_len;
0615     ci->i_xattrs.vals_size += val_len;
0616     if (val)
0617         xattr->val = val;
0618     else
0619         xattr->val = "";
0620 
0621     xattr->val_len = val_len;
0622     xattr->dirty = update_xattr;
0623     xattr->should_free_val = (val && update_xattr);
0624 
0625     if (new) {
0626         rb_link_node(&xattr->node, parent, p);
0627         rb_insert_color(&xattr->node, &ci->i_xattrs.index);
0628         dout("__set_xattr_val p=%p\n", p);
0629     }
0630 
0631     dout("__set_xattr_val added %llx.%llx xattr %p %.*s=%.*s\n",
0632          ceph_vinop(&ci->netfs.inode), xattr, name_len, name, val_len, val);
0633 
0634     return 0;
0635 }
0636 
0637 static struct ceph_inode_xattr *__get_xattr(struct ceph_inode_info *ci,
0638                const char *name)
0639 {
0640     struct rb_node **p;
0641     struct rb_node *parent = NULL;
0642     struct ceph_inode_xattr *xattr = NULL;
0643     int name_len = strlen(name);
0644     int c;
0645 
0646     p = &ci->i_xattrs.index.rb_node;
0647     while (*p) {
0648         parent = *p;
0649         xattr = rb_entry(parent, struct ceph_inode_xattr, node);
0650         c = strncmp(name, xattr->name, xattr->name_len);
0651         if (c == 0 && name_len > xattr->name_len)
0652             c = 1;
0653         if (c < 0)
0654             p = &(*p)->rb_left;
0655         else if (c > 0)
0656             p = &(*p)->rb_right;
0657         else {
0658             dout("__get_xattr %s: found %.*s\n", name,
0659                  xattr->val_len, xattr->val);
0660             return xattr;
0661         }
0662     }
0663 
0664     dout("__get_xattr %s: not found\n", name);
0665 
0666     return NULL;
0667 }
0668 
0669 static void __free_xattr(struct ceph_inode_xattr *xattr)
0670 {
0671     BUG_ON(!xattr);
0672 
0673     if (xattr->should_free_name)
0674         kfree(xattr->name);
0675     if (xattr->should_free_val)
0676         kfree(xattr->val);
0677 
0678     kfree(xattr);
0679 }
0680 
0681 static int __remove_xattr(struct ceph_inode_info *ci,
0682               struct ceph_inode_xattr *xattr)
0683 {
0684     if (!xattr)
0685         return -ENODATA;
0686 
0687     rb_erase(&xattr->node, &ci->i_xattrs.index);
0688 
0689     if (xattr->should_free_name)
0690         kfree(xattr->name);
0691     if (xattr->should_free_val)
0692         kfree(xattr->val);
0693 
0694     ci->i_xattrs.names_size -= xattr->name_len;
0695     ci->i_xattrs.vals_size -= xattr->val_len;
0696     ci->i_xattrs.count--;
0697     kfree(xattr);
0698 
0699     return 0;
0700 }
0701 
0702 static char *__copy_xattr_names(struct ceph_inode_info *ci,
0703                 char *dest)
0704 {
0705     struct rb_node *p;
0706     struct ceph_inode_xattr *xattr = NULL;
0707 
0708     p = rb_first(&ci->i_xattrs.index);
0709     dout("__copy_xattr_names count=%d\n", ci->i_xattrs.count);
0710 
0711     while (p) {
0712         xattr = rb_entry(p, struct ceph_inode_xattr, node);
0713         memcpy(dest, xattr->name, xattr->name_len);
0714         dest[xattr->name_len] = '\0';
0715 
0716         dout("dest=%s %p (%s) (%d/%d)\n", dest, xattr, xattr->name,
0717              xattr->name_len, ci->i_xattrs.names_size);
0718 
0719         dest += xattr->name_len + 1;
0720         p = rb_next(p);
0721     }
0722 
0723     return dest;
0724 }
0725 
0726 void __ceph_destroy_xattrs(struct ceph_inode_info *ci)
0727 {
0728     struct rb_node *p, *tmp;
0729     struct ceph_inode_xattr *xattr = NULL;
0730 
0731     p = rb_first(&ci->i_xattrs.index);
0732 
0733     dout("__ceph_destroy_xattrs p=%p\n", p);
0734 
0735     while (p) {
0736         xattr = rb_entry(p, struct ceph_inode_xattr, node);
0737         tmp = p;
0738         p = rb_next(tmp);
0739         dout("__ceph_destroy_xattrs next p=%p (%.*s)\n", p,
0740              xattr->name_len, xattr->name);
0741         rb_erase(tmp, &ci->i_xattrs.index);
0742 
0743         __free_xattr(xattr);
0744     }
0745 
0746     ci->i_xattrs.names_size = 0;
0747     ci->i_xattrs.vals_size = 0;
0748     ci->i_xattrs.index_version = 0;
0749     ci->i_xattrs.count = 0;
0750     ci->i_xattrs.index = RB_ROOT;
0751 }
0752 
0753 static int __build_xattrs(struct inode *inode)
0754     __releases(ci->i_ceph_lock)
0755     __acquires(ci->i_ceph_lock)
0756 {
0757     u32 namelen;
0758     u32 numattr = 0;
0759     void *p, *end;
0760     u32 len;
0761     const char *name, *val;
0762     struct ceph_inode_info *ci = ceph_inode(inode);
0763     u64 xattr_version;
0764     struct ceph_inode_xattr **xattrs = NULL;
0765     int err = 0;
0766     int i;
0767 
0768     dout("__build_xattrs() len=%d\n",
0769          ci->i_xattrs.blob ? (int)ci->i_xattrs.blob->vec.iov_len : 0);
0770 
0771     if (ci->i_xattrs.index_version >= ci->i_xattrs.version)
0772         return 0; /* already built */
0773 
0774     __ceph_destroy_xattrs(ci);
0775 
0776 start:
0777     /* updated internal xattr rb tree */
0778     if (ci->i_xattrs.blob && ci->i_xattrs.blob->vec.iov_len > 4) {
0779         p = ci->i_xattrs.blob->vec.iov_base;
0780         end = p + ci->i_xattrs.blob->vec.iov_len;
0781         ceph_decode_32_safe(&p, end, numattr, bad);
0782         xattr_version = ci->i_xattrs.version;
0783         spin_unlock(&ci->i_ceph_lock);
0784 
0785         xattrs = kcalloc(numattr, sizeof(struct ceph_inode_xattr *),
0786                  GFP_NOFS);
0787         err = -ENOMEM;
0788         if (!xattrs)
0789             goto bad_lock;
0790 
0791         for (i = 0; i < numattr; i++) {
0792             xattrs[i] = kmalloc(sizeof(struct ceph_inode_xattr),
0793                         GFP_NOFS);
0794             if (!xattrs[i])
0795                 goto bad_lock;
0796         }
0797 
0798         spin_lock(&ci->i_ceph_lock);
0799         if (ci->i_xattrs.version != xattr_version) {
0800             /* lost a race, retry */
0801             for (i = 0; i < numattr; i++)
0802                 kfree(xattrs[i]);
0803             kfree(xattrs);
0804             xattrs = NULL;
0805             goto start;
0806         }
0807         err = -EIO;
0808         while (numattr--) {
0809             ceph_decode_32_safe(&p, end, len, bad);
0810             namelen = len;
0811             name = p;
0812             p += len;
0813             ceph_decode_32_safe(&p, end, len, bad);
0814             val = p;
0815             p += len;
0816 
0817             err = __set_xattr(ci, name, namelen, val, len,
0818                       0, 0, &xattrs[numattr]);
0819 
0820             if (err < 0)
0821                 goto bad;
0822         }
0823         kfree(xattrs);
0824     }
0825     ci->i_xattrs.index_version = ci->i_xattrs.version;
0826     ci->i_xattrs.dirty = false;
0827 
0828     return err;
0829 bad_lock:
0830     spin_lock(&ci->i_ceph_lock);
0831 bad:
0832     if (xattrs) {
0833         for (i = 0; i < numattr; i++)
0834             kfree(xattrs[i]);
0835         kfree(xattrs);
0836     }
0837     ci->i_xattrs.names_size = 0;
0838     return err;
0839 }
0840 
0841 static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size,
0842                     int val_size)
0843 {
0844     /*
0845      * 4 bytes for the length, and additional 4 bytes per each xattr name,
0846      * 4 bytes per each value
0847      */
0848     int size = 4 + ci->i_xattrs.count*(4 + 4) +
0849                  ci->i_xattrs.names_size +
0850                  ci->i_xattrs.vals_size;
0851     dout("__get_required_blob_size c=%d names.size=%d vals.size=%d\n",
0852          ci->i_xattrs.count, ci->i_xattrs.names_size,
0853          ci->i_xattrs.vals_size);
0854 
0855     if (name_size)
0856         size += 4 + 4 + name_size + val_size;
0857 
0858     return size;
0859 }
0860 
0861 /*
0862  * If there are dirty xattrs, reencode xattrs into the prealloc_blob
0863  * and swap into place.  It returns the old i_xattrs.blob (or NULL) so
0864  * that it can be freed by the caller as the i_ceph_lock is likely to be
0865  * held.
0866  */
0867 struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci)
0868 {
0869     struct rb_node *p;
0870     struct ceph_inode_xattr *xattr = NULL;
0871     struct ceph_buffer *old_blob = NULL;
0872     void *dest;
0873 
0874     dout("__build_xattrs_blob %p\n", &ci->netfs.inode);
0875     if (ci->i_xattrs.dirty) {
0876         int need = __get_required_blob_size(ci, 0, 0);
0877 
0878         BUG_ON(need > ci->i_xattrs.prealloc_blob->alloc_len);
0879 
0880         p = rb_first(&ci->i_xattrs.index);
0881         dest = ci->i_xattrs.prealloc_blob->vec.iov_base;
0882 
0883         ceph_encode_32(&dest, ci->i_xattrs.count);
0884         while (p) {
0885             xattr = rb_entry(p, struct ceph_inode_xattr, node);
0886 
0887             ceph_encode_32(&dest, xattr->name_len);
0888             memcpy(dest, xattr->name, xattr->name_len);
0889             dest += xattr->name_len;
0890             ceph_encode_32(&dest, xattr->val_len);
0891             memcpy(dest, xattr->val, xattr->val_len);
0892             dest += xattr->val_len;
0893 
0894             p = rb_next(p);
0895         }
0896 
0897         /* adjust buffer len; it may be larger than we need */
0898         ci->i_xattrs.prealloc_blob->vec.iov_len =
0899             dest - ci->i_xattrs.prealloc_blob->vec.iov_base;
0900 
0901         if (ci->i_xattrs.blob)
0902             old_blob = ci->i_xattrs.blob;
0903         ci->i_xattrs.blob = ci->i_xattrs.prealloc_blob;
0904         ci->i_xattrs.prealloc_blob = NULL;
0905         ci->i_xattrs.dirty = false;
0906         ci->i_xattrs.version++;
0907     }
0908 
0909     return old_blob;
0910 }
0911 
0912 static inline int __get_request_mask(struct inode *in) {
0913     struct ceph_mds_request *req = current->journal_info;
0914     int mask = 0;
0915     if (req && req->r_target_inode == in) {
0916         if (req->r_op == CEPH_MDS_OP_LOOKUP ||
0917             req->r_op == CEPH_MDS_OP_LOOKUPINO ||
0918             req->r_op == CEPH_MDS_OP_LOOKUPPARENT ||
0919             req->r_op == CEPH_MDS_OP_GETATTR) {
0920             mask = le32_to_cpu(req->r_args.getattr.mask);
0921         } else if (req->r_op == CEPH_MDS_OP_OPEN ||
0922                req->r_op == CEPH_MDS_OP_CREATE) {
0923             mask = le32_to_cpu(req->r_args.open.mask);
0924         }
0925     }
0926     return mask;
0927 }
0928 
0929 ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
0930               size_t size)
0931 {
0932     struct ceph_inode_info *ci = ceph_inode(inode);
0933     struct ceph_inode_xattr *xattr;
0934     struct ceph_vxattr *vxattr;
0935     int req_mask;
0936     ssize_t err;
0937 
0938     if (strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN))
0939         goto handle_non_vxattrs;
0940 
0941     /* let's see if a virtual xattr was requested */
0942     vxattr = ceph_match_vxattr(inode, name);
0943     if (vxattr) {
0944         int mask = 0;
0945         if (vxattr->flags & VXATTR_FLAG_RSTAT)
0946             mask |= CEPH_STAT_RSTAT;
0947         if (vxattr->flags & VXATTR_FLAG_DIRSTAT)
0948             mask |= CEPH_CAP_FILE_SHARED;
0949         err = ceph_do_getattr(inode, mask, true);
0950         if (err)
0951             return err;
0952         err = -ENODATA;
0953         if (!(vxattr->exists_cb && !vxattr->exists_cb(ci))) {
0954             err = vxattr->getxattr_cb(ci, value, size);
0955             if (size && size < err)
0956                 err = -ERANGE;
0957         }
0958         return err;
0959     } else {
0960         err = ceph_do_getvxattr(inode, name, value, size);
0961         /* this would happen with a new client and old server combo */
0962         if (err == -EOPNOTSUPP)
0963             err = -ENODATA;
0964         return err;
0965     }
0966 handle_non_vxattrs:
0967     req_mask = __get_request_mask(inode);
0968 
0969     spin_lock(&ci->i_ceph_lock);
0970     dout("getxattr %p name '%s' ver=%lld index_ver=%lld\n", inode, name,
0971          ci->i_xattrs.version, ci->i_xattrs.index_version);
0972 
0973     if (ci->i_xattrs.version == 0 ||
0974         !((req_mask & CEPH_CAP_XATTR_SHARED) ||
0975           __ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1))) {
0976         spin_unlock(&ci->i_ceph_lock);
0977 
0978         /* security module gets xattr while filling trace */
0979         if (current->journal_info) {
0980             pr_warn_ratelimited("sync getxattr %p "
0981                         "during filling trace\n", inode);
0982             return -EBUSY;
0983         }
0984 
0985         /* get xattrs from mds (if we don't already have them) */
0986         err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true);
0987         if (err)
0988             return err;
0989         spin_lock(&ci->i_ceph_lock);
0990     }
0991 
0992     err = __build_xattrs(inode);
0993     if (err < 0)
0994         goto out;
0995 
0996     err = -ENODATA;  /* == ENOATTR */
0997     xattr = __get_xattr(ci, name);
0998     if (!xattr)
0999         goto out;
1000 
1001     err = -ERANGE;
1002     if (size && size < xattr->val_len)
1003         goto out;
1004 
1005     err = xattr->val_len;
1006     if (size == 0)
1007         goto out;
1008 
1009     memcpy(value, xattr->val, xattr->val_len);
1010 
1011     if (current->journal_info &&
1012         !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
1013         security_ismaclabel(name + XATTR_SECURITY_PREFIX_LEN))
1014         ci->i_ceph_flags |= CEPH_I_SEC_INITED;
1015 out:
1016     spin_unlock(&ci->i_ceph_lock);
1017     return err;
1018 }
1019 
1020 ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
1021 {
1022     struct inode *inode = d_inode(dentry);
1023     struct ceph_inode_info *ci = ceph_inode(inode);
1024     bool len_only = (size == 0);
1025     u32 namelen;
1026     int err;
1027 
1028     spin_lock(&ci->i_ceph_lock);
1029     dout("listxattr %p ver=%lld index_ver=%lld\n", inode,
1030          ci->i_xattrs.version, ci->i_xattrs.index_version);
1031 
1032     if (ci->i_xattrs.version == 0 ||
1033         !__ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1)) {
1034         spin_unlock(&ci->i_ceph_lock);
1035         err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true);
1036         if (err)
1037             return err;
1038         spin_lock(&ci->i_ceph_lock);
1039     }
1040 
1041     err = __build_xattrs(inode);
1042     if (err < 0)
1043         goto out;
1044 
1045     /* add 1 byte for each xattr due to the null termination */
1046     namelen = ci->i_xattrs.names_size + ci->i_xattrs.count;
1047     if (!len_only) {
1048         if (namelen > size) {
1049             err = -ERANGE;
1050             goto out;
1051         }
1052         names = __copy_xattr_names(ci, names);
1053         size -= namelen;
1054     }
1055     err = namelen;
1056 out:
1057     spin_unlock(&ci->i_ceph_lock);
1058     return err;
1059 }
1060 
1061 static int ceph_sync_setxattr(struct inode *inode, const char *name,
1062                   const char *value, size_t size, int flags)
1063 {
1064     struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
1065     struct ceph_inode_info *ci = ceph_inode(inode);
1066     struct ceph_mds_request *req;
1067     struct ceph_mds_client *mdsc = fsc->mdsc;
1068     struct ceph_osd_client *osdc = &fsc->client->osdc;
1069     struct ceph_pagelist *pagelist = NULL;
1070     int op = CEPH_MDS_OP_SETXATTR;
1071     int err;
1072 
1073     if (size > 0) {
1074         /* copy value into pagelist */
1075         pagelist = ceph_pagelist_alloc(GFP_NOFS);
1076         if (!pagelist)
1077             return -ENOMEM;
1078 
1079         err = ceph_pagelist_append(pagelist, value, size);
1080         if (err)
1081             goto out;
1082     } else if (!value) {
1083         if (flags & CEPH_XATTR_REPLACE)
1084             op = CEPH_MDS_OP_RMXATTR;
1085         else
1086             flags |= CEPH_XATTR_REMOVE;
1087     }
1088 
1089     dout("setxattr value size: %zu\n", size);
1090 
1091     /* do request */
1092     req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
1093     if (IS_ERR(req)) {
1094         err = PTR_ERR(req);
1095         goto out;
1096     }
1097 
1098     req->r_path2 = kstrdup(name, GFP_NOFS);
1099     if (!req->r_path2) {
1100         ceph_mdsc_put_request(req);
1101         err = -ENOMEM;
1102         goto out;
1103     }
1104 
1105     if (op == CEPH_MDS_OP_SETXATTR) {
1106         req->r_args.setxattr.flags = cpu_to_le32(flags);
1107         req->r_args.setxattr.osdmap_epoch =
1108             cpu_to_le32(osdc->osdmap->epoch);
1109         req->r_pagelist = pagelist;
1110         pagelist = NULL;
1111     }
1112 
1113     req->r_inode = inode;
1114     ihold(inode);
1115     req->r_num_caps = 1;
1116     req->r_inode_drop = CEPH_CAP_XATTR_SHARED;
1117 
1118     dout("xattr.ver (before): %lld\n", ci->i_xattrs.version);
1119     err = ceph_mdsc_do_request(mdsc, NULL, req);
1120     ceph_mdsc_put_request(req);
1121     dout("xattr.ver (after): %lld\n", ci->i_xattrs.version);
1122 
1123 out:
1124     if (pagelist)
1125         ceph_pagelist_release(pagelist);
1126     return err;
1127 }
1128 
1129 int __ceph_setxattr(struct inode *inode, const char *name,
1130             const void *value, size_t size, int flags)
1131 {
1132     struct ceph_vxattr *vxattr;
1133     struct ceph_inode_info *ci = ceph_inode(inode);
1134     struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
1135     struct ceph_cap_flush *prealloc_cf = NULL;
1136     struct ceph_buffer *old_blob = NULL;
1137     int issued;
1138     int err;
1139     int dirty = 0;
1140     int name_len = strlen(name);
1141     int val_len = size;
1142     char *newname = NULL;
1143     char *newval = NULL;
1144     struct ceph_inode_xattr *xattr = NULL;
1145     int required_blob_size;
1146     bool check_realm = false;
1147     bool lock_snap_rwsem = false;
1148 
1149     if (ceph_snap(inode) != CEPH_NOSNAP)
1150         return -EROFS;
1151 
1152     vxattr = ceph_match_vxattr(inode, name);
1153     if (vxattr) {
1154         if (vxattr->flags & VXATTR_FLAG_READONLY)
1155             return -EOPNOTSUPP;
1156         if (value && !strncmp(vxattr->name, "ceph.quota", 10))
1157             check_realm = true;
1158     }
1159 
1160     /* pass any unhandled ceph.* xattrs through to the MDS */
1161     if (!strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN))
1162         goto do_sync_unlocked;
1163 
1164     /* preallocate memory for xattr name, value, index node */
1165     err = -ENOMEM;
1166     newname = kmemdup(name, name_len + 1, GFP_NOFS);
1167     if (!newname)
1168         goto out;
1169 
1170     if (val_len) {
1171         newval = kmemdup(value, val_len, GFP_NOFS);
1172         if (!newval)
1173             goto out;
1174     }
1175 
1176     xattr = kmalloc(sizeof(struct ceph_inode_xattr), GFP_NOFS);
1177     if (!xattr)
1178         goto out;
1179 
1180     prealloc_cf = ceph_alloc_cap_flush();
1181     if (!prealloc_cf)
1182         goto out;
1183 
1184     spin_lock(&ci->i_ceph_lock);
1185 retry:
1186     issued = __ceph_caps_issued(ci, NULL);
1187     required_blob_size = __get_required_blob_size(ci, name_len, val_len);
1188     if ((ci->i_xattrs.version == 0) || !(issued & CEPH_CAP_XATTR_EXCL) ||
1189         (required_blob_size > mdsc->mdsmap->m_max_xattr_size)) {
1190         dout("%s do sync setxattr: version: %llu size: %d max: %llu\n",
1191              __func__, ci->i_xattrs.version, required_blob_size,
1192              mdsc->mdsmap->m_max_xattr_size);
1193         goto do_sync;
1194     }
1195 
1196     if (!lock_snap_rwsem && !ci->i_head_snapc) {
1197         lock_snap_rwsem = true;
1198         if (!down_read_trylock(&mdsc->snap_rwsem)) {
1199             spin_unlock(&ci->i_ceph_lock);
1200             down_read(&mdsc->snap_rwsem);
1201             spin_lock(&ci->i_ceph_lock);
1202             goto retry;
1203         }
1204     }
1205 
1206     dout("setxattr %p name '%s' issued %s\n", inode, name,
1207          ceph_cap_string(issued));
1208     __build_xattrs(inode);
1209 
1210     if (!ci->i_xattrs.prealloc_blob ||
1211         required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) {
1212         struct ceph_buffer *blob;
1213 
1214         spin_unlock(&ci->i_ceph_lock);
1215         ceph_buffer_put(old_blob); /* Shouldn't be required */
1216         dout(" pre-allocating new blob size=%d\n", required_blob_size);
1217         blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
1218         if (!blob)
1219             goto do_sync_unlocked;
1220         spin_lock(&ci->i_ceph_lock);
1221         /* prealloc_blob can't be released while holding i_ceph_lock */
1222         if (ci->i_xattrs.prealloc_blob)
1223             old_blob = ci->i_xattrs.prealloc_blob;
1224         ci->i_xattrs.prealloc_blob = blob;
1225         goto retry;
1226     }
1227 
1228     err = __set_xattr(ci, newname, name_len, newval, val_len,
1229               flags, value ? 1 : -1, &xattr);
1230 
1231     if (!err) {
1232         dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL,
1233                            &prealloc_cf);
1234         ci->i_xattrs.dirty = true;
1235         inode->i_ctime = current_time(inode);
1236     }
1237 
1238     spin_unlock(&ci->i_ceph_lock);
1239     ceph_buffer_put(old_blob);
1240     if (lock_snap_rwsem)
1241         up_read(&mdsc->snap_rwsem);
1242     if (dirty)
1243         __mark_inode_dirty(inode, dirty);
1244     ceph_free_cap_flush(prealloc_cf);
1245     return err;
1246 
1247 do_sync:
1248     spin_unlock(&ci->i_ceph_lock);
1249 do_sync_unlocked:
1250     if (lock_snap_rwsem)
1251         up_read(&mdsc->snap_rwsem);
1252 
1253     /* security module set xattr while filling trace */
1254     if (current->journal_info) {
1255         pr_warn_ratelimited("sync setxattr %p "
1256                     "during filling trace\n", inode);
1257         err = -EBUSY;
1258     } else {
1259         err = ceph_sync_setxattr(inode, name, value, size, flags);
1260         if (err >= 0 && check_realm) {
1261             /* check if snaprealm was created for quota inode */
1262             spin_lock(&ci->i_ceph_lock);
1263             if ((ci->i_max_files || ci->i_max_bytes) &&
1264                 !(ci->i_snap_realm &&
1265                   ci->i_snap_realm->ino == ci->i_vino.ino))
1266                 err = -EOPNOTSUPP;
1267             spin_unlock(&ci->i_ceph_lock);
1268         }
1269     }
1270 out:
1271     ceph_free_cap_flush(prealloc_cf);
1272     kfree(newname);
1273     kfree(newval);
1274     kfree(xattr);
1275     return err;
1276 }
1277 
1278 static int ceph_get_xattr_handler(const struct xattr_handler *handler,
1279                   struct dentry *dentry, struct inode *inode,
1280                   const char *name, void *value, size_t size)
1281 {
1282     if (!ceph_is_valid_xattr(name))
1283         return -EOPNOTSUPP;
1284     return __ceph_getxattr(inode, name, value, size);
1285 }
1286 
1287 static int ceph_set_xattr_handler(const struct xattr_handler *handler,
1288                   struct user_namespace *mnt_userns,
1289                   struct dentry *unused, struct inode *inode,
1290                   const char *name, const void *value,
1291                   size_t size, int flags)
1292 {
1293     if (!ceph_is_valid_xattr(name))
1294         return -EOPNOTSUPP;
1295     return __ceph_setxattr(inode, name, value, size, flags);
1296 }
1297 
1298 static const struct xattr_handler ceph_other_xattr_handler = {
1299     .prefix = "",  /* match any name => handlers called with full name */
1300     .get = ceph_get_xattr_handler,
1301     .set = ceph_set_xattr_handler,
1302 };
1303 
1304 #ifdef CONFIG_SECURITY
1305 bool ceph_security_xattr_wanted(struct inode *in)
1306 {
1307     return in->i_security != NULL;
1308 }
1309 
1310 bool ceph_security_xattr_deadlock(struct inode *in)
1311 {
1312     struct ceph_inode_info *ci;
1313     bool ret;
1314     if (!in->i_security)
1315         return false;
1316     ci = ceph_inode(in);
1317     spin_lock(&ci->i_ceph_lock);
1318     ret = !(ci->i_ceph_flags & CEPH_I_SEC_INITED) &&
1319           !(ci->i_xattrs.version > 0 &&
1320         __ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 0));
1321     spin_unlock(&ci->i_ceph_lock);
1322     return ret;
1323 }
1324 
1325 #ifdef CONFIG_CEPH_FS_SECURITY_LABEL
1326 int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
1327                struct ceph_acl_sec_ctx *as_ctx)
1328 {
1329     struct ceph_pagelist *pagelist = as_ctx->pagelist;
1330     const char *name;
1331     size_t name_len;
1332     int err;
1333 
1334     err = security_dentry_init_security(dentry, mode, &dentry->d_name,
1335                         &name, &as_ctx->sec_ctx,
1336                         &as_ctx->sec_ctxlen);
1337     if (err < 0) {
1338         WARN_ON_ONCE(err != -EOPNOTSUPP);
1339         err = 0; /* do nothing */
1340         goto out;
1341     }
1342 
1343     err = -ENOMEM;
1344     if (!pagelist) {
1345         pagelist = ceph_pagelist_alloc(GFP_KERNEL);
1346         if (!pagelist)
1347             goto out;
1348         err = ceph_pagelist_reserve(pagelist, PAGE_SIZE);
1349         if (err)
1350             goto out;
1351         ceph_pagelist_encode_32(pagelist, 1);
1352     }
1353 
1354     /*
1355      * FIXME: Make security_dentry_init_security() generic. Currently
1356      * It only supports single security module and only selinux has
1357      * dentry_init_security hook.
1358      */
1359     name_len = strlen(name);
1360     err = ceph_pagelist_reserve(pagelist,
1361                     4 * 2 + name_len + as_ctx->sec_ctxlen);
1362     if (err)
1363         goto out;
1364 
1365     if (as_ctx->pagelist) {
1366         /* update count of KV pairs */
1367         BUG_ON(pagelist->length <= sizeof(__le32));
1368         if (list_is_singular(&pagelist->head)) {
1369             le32_add_cpu((__le32*)pagelist->mapped_tail, 1);
1370         } else {
1371             struct page *page = list_first_entry(&pagelist->head,
1372                                  struct page, lru);
1373             void *addr = kmap_atomic(page);
1374             le32_add_cpu((__le32*)addr, 1);
1375             kunmap_atomic(addr);
1376         }
1377     } else {
1378         as_ctx->pagelist = pagelist;
1379     }
1380 
1381     ceph_pagelist_encode_32(pagelist, name_len);
1382     ceph_pagelist_append(pagelist, name, name_len);
1383 
1384     ceph_pagelist_encode_32(pagelist, as_ctx->sec_ctxlen);
1385     ceph_pagelist_append(pagelist, as_ctx->sec_ctx, as_ctx->sec_ctxlen);
1386 
1387     err = 0;
1388 out:
1389     if (pagelist && !as_ctx->pagelist)
1390         ceph_pagelist_release(pagelist);
1391     return err;
1392 }
1393 #endif /* CONFIG_CEPH_FS_SECURITY_LABEL */
1394 #endif /* CONFIG_SECURITY */
1395 
1396 void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
1397 {
1398 #ifdef CONFIG_CEPH_FS_POSIX_ACL
1399     posix_acl_release(as_ctx->acl);
1400     posix_acl_release(as_ctx->default_acl);
1401 #endif
1402 #ifdef CONFIG_CEPH_FS_SECURITY_LABEL
1403     security_release_secctx(as_ctx->sec_ctx, as_ctx->sec_ctxlen);
1404 #endif
1405     if (as_ctx->pagelist)
1406         ceph_pagelist_release(as_ctx->pagelist);
1407 }
1408 
1409 /*
1410  * List of handlers for synthetic system.* attributes. Other
1411  * attributes are handled directly.
1412  */
1413 const struct xattr_handler *ceph_xattr_handlers[] = {
1414 #ifdef CONFIG_CEPH_FS_POSIX_ACL
1415     &posix_acl_access_xattr_handler,
1416     &posix_acl_default_xattr_handler,
1417 #endif
1418     &ceph_other_xattr_handler,
1419     NULL,
1420 };