+static int osd_xattr_set_pfid(const struct lu_env *env, struct osd_object *obj,
+ const struct lu_buf *buf, int fl,
+ struct thandle *handle)
+{
+ struct osd_thread_info *info = osd_oti_get(env);
+ struct dentry *dentry = &info->oti_obj_dentry;
+ struct lustre_ost_attrs *loa = &info->oti_ost_attrs;
+ struct lustre_mdt_attrs *lma = &loa->loa_lma;
+ struct inode *inode = obj->oo_inode;
+ struct filter_fid *ff = buf->lb_buf;
+ struct ost_layout *ol = &ff->ff_layout;
+ int flags = XATTR_REPLACE;
+ int rc;
+ ENTRY;
+
+ if (buf->lb_len != sizeof(*ff) && buf->lb_len != sizeof(struct lu_fid))
+ RETURN(-EINVAL);
+
+ rc = osd_get_lma(info, inode, dentry, loa);
+ if (rc == -ENODATA) {
+ /* Usually for upgarding from old device */
+ lustre_loa_init(loa, lu_object_fid(&obj->oo_dt.do_lu),
+ LMAC_FID_ON_OST, 0);
+ flags = XATTR_CREATE;
+ } else if (rc) {
+ RETURN(rc);
+ }
+
+ if (!rc && lma->lma_compat & LMAC_STRIPE_INFO) {
+ if ((fl & LU_XATTR_CREATE) && !(fl & LU_XATTR_REPLACE))
+ RETURN(-EEXIST);
+
+ if (LDISKFS_INODE_SIZE(inode->i_sb) > 256) {
+ /* Separate PFID EA from LMA */
+ lma->lma_compat &= ~(LMAC_STRIPE_INFO | LMAC_COMP_INFO);
+ lustre_lma_swab(lma);
+ rc = __osd_xattr_set(info, inode, XATTR_NAME_LMA, lma,
+ sizeof(*lma), XATTR_REPLACE);
+ if (!rc) {
+ obj->oo_pfid_in_lma = 0;
+ rc = LU_XATTR_CREATE;
+ }
+
+ RETURN(rc);
+ }
+ } else {
+ if (LDISKFS_INODE_SIZE(inode->i_sb) > 256)
+ RETURN(fl);
+
+ /* Old client does not send stripe information,
+ * then store the PFID EA on disk separatedly. */
+ if (unlikely(buf->lb_len == sizeof(struct lu_fid) ||
+ ol->ol_stripe_size == 0))
+ RETURN(fl);
+
+ /* Remove old PFID EA entry firstly. */
+ ll_vfs_dq_init(inode);
+ rc = inode->i_op->removexattr(dentry, XATTR_NAME_FID);
+ if (rc == -ENODATA) {
+ if ((fl & LU_XATTR_REPLACE) && !(fl & LU_XATTR_CREATE))
+ RETURN(rc);
+ } else if (rc) {
+ RETURN(rc);
+ }
+ }
+
+ fid_le_to_cpu(&loa->loa_parent_fid, &ff->ff_parent);
+ if (likely(ol->ol_stripe_size != 0)) {
+ loa->loa_parent_fid.f_ver |= le32_to_cpu(ol->ol_stripe_count) <<
+ PFID_STRIPE_IDX_BITS;
+ loa->loa_stripe_size = le32_to_cpu(ol->ol_stripe_size);
+ lma->lma_compat |= LMAC_STRIPE_INFO;
+ if (ol->ol_comp_id != 0) {
+ loa->loa_comp_id = le32_to_cpu(ol->ol_comp_id);
+ loa->loa_comp_start = le64_to_cpu(ol->ol_comp_start);
+ loa->loa_comp_end = le64_to_cpu(ol->ol_comp_end);
+ lma->lma_compat |= LMAC_COMP_INFO;
+ }
+ }
+
+ lustre_loa_swab(loa, false);
+
+ /* Store the PFID EA inside LMA. */
+ rc = __osd_xattr_set(info, inode, XATTR_NAME_LMA, loa, sizeof(*loa),
+ flags);
+ if (!rc)
+ obj->oo_pfid_in_lma = 1;
+
+ RETURN(rc);
+}
+