-static int mdd_path2fid(const struct lu_env *env, struct mdd_device *mdd,
- const char *path, struct lu_fid *fid)
-{
- struct lu_buf *buf;
- struct lu_fid *f = &mdd_env_info(env)->mti_fid;
- struct mdd_object *obj;
- struct lu_name *lname = &mdd_env_info(env)->mti_name;
- char *name;
- int rc = 0;
- ENTRY;
-
- /* temp buffer for path element */
- buf = mdd_buf_alloc(env, PATH_MAX);
- if (buf->lb_buf == NULL)
- RETURN(-ENOMEM);
-
- lname->ln_name = name = buf->lb_buf;
- lname->ln_namelen = 0;
- *f = mdd->mdd_root_fid;
-
- while(1) {
- while (*path == '/')
- path++;
- if (*path == '\0')
- break;
- while (*path != '/' && *path != '\0') {
- *name = *path;
- path++;
- name++;
- lname->ln_namelen++;
- }
-
- *name = '\0';
- /* find obj corresponding to fid */
- obj = mdd_object_find(env, mdd, f);
- if (obj == NULL)
- GOTO(out, rc = -EREMOTE);
- if (IS_ERR(obj))
- GOTO(out, rc = PTR_ERR(obj));
- /* get child fid from parent and name */
- rc = mdd_lookup(env, &obj->mod_obj, lname, f, NULL);
- mdd_object_put(env, obj);
- if (rc)
- break;
-
- name = buf->lb_buf;
- lname->ln_namelen = 0;
- }
-
- if (!rc)
- *fid = *f;
-out:
- RETURN(rc);
-}
-
-/** The maximum depth that fid2path() will search.
- * This is limited only because we want to store the fids for
- * historical path lookup purposes.
- */
-#define MAX_PATH_DEPTH 100
-
-/** mdd_path() lookup structure. */
-struct path_lookup_info {
- __u64 pli_recno; /**< history point */
- __u64 pli_currec; /**< current record */
- struct lu_fid pli_fid;
- struct lu_fid pli_fids[MAX_PATH_DEPTH]; /**< path, in fids */
- struct mdd_object *pli_mdd_obj;
- char *pli_path; /**< full path */
- int pli_pathlen;
- int pli_linkno; /**< which hardlink to follow */
- int pli_fidcount; /**< number of \a pli_fids */
-};
-
-static int mdd_path_current(const struct lu_env *env,
- struct path_lookup_info *pli)
-{
- struct mdd_device *mdd = mdo2mdd(&pli->pli_mdd_obj->mod_obj);
- struct mdd_object *mdd_obj;
- struct lu_buf *buf = NULL;
- struct link_ea_header *leh;
- struct link_ea_entry *lee;
- struct lu_name *tmpname = &mdd_env_info(env)->mti_name;
- struct lu_fid *tmpfid = &mdd_env_info(env)->mti_fid;
- char *ptr;
- int reclen;
- int rc;
- ENTRY;
-
- ptr = pli->pli_path + pli->pli_pathlen - 1;
- *ptr = 0;
- --ptr;
- pli->pli_fidcount = 0;
- pli->pli_fids[0] = *(struct lu_fid *)mdd_object_fid(pli->pli_mdd_obj);
-
- while (!mdd_is_root(mdd, &pli->pli_fids[pli->pli_fidcount])) {
- mdd_obj = mdd_object_find(env, mdd,
- &pli->pli_fids[pli->pli_fidcount]);
- if (mdd_obj == NULL)
- GOTO(out, rc = -EREMOTE);
- if (IS_ERR(mdd_obj))
- GOTO(out, rc = PTR_ERR(mdd_obj));
- rc = lu_object_exists(&mdd_obj->mod_obj.mo_lu);
- if (rc <= 0) {
- mdd_object_put(env, mdd_obj);
- if (rc == -1)
- rc = -EREMOTE;
- else if (rc == 0)
- /* Do I need to error out here? */
- rc = -ENOENT;
- GOTO(out, rc);
- }
-
- /* Get parent fid and object name */
- mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
- buf = mdd_links_get(env, mdd_obj);
- mdd_read_unlock(env, mdd_obj);
- mdd_object_put(env, mdd_obj);
- if (IS_ERR(buf))
- GOTO(out, rc = PTR_ERR(buf));
-
- leh = buf->lb_buf;
- lee = (struct link_ea_entry *)(leh + 1); /* link #0 */
- mdd_lee_unpack(lee, &reclen, tmpname, tmpfid);
-
- /* If set, use link #linkno for path lookup, otherwise use
- link #0. Only do this for the final path element. */
- if ((pli->pli_fidcount == 0) &&
- (pli->pli_linkno < leh->leh_reccount)) {
- int count;
- for (count = 0; count < pli->pli_linkno; count++) {
- lee = (struct link_ea_entry *)
- ((char *)lee + reclen);
- mdd_lee_unpack(lee, &reclen, tmpname, tmpfid);
- }
- if (pli->pli_linkno < leh->leh_reccount - 1)
- /* indicate to user there are more links */
- pli->pli_linkno++;
- }
-
- /* Pack the name in the end of the buffer */
- ptr -= tmpname->ln_namelen;
- if (ptr - 1 <= pli->pli_path)
- GOTO(out, rc = -EOVERFLOW);
- strncpy(ptr, tmpname->ln_name, tmpname->ln_namelen);
- *(--ptr) = '/';
-
- /* Store the parent fid for historic lookup */
- if (++pli->pli_fidcount >= MAX_PATH_DEPTH)
- GOTO(out, rc = -EOVERFLOW);
- pli->pli_fids[pli->pli_fidcount] = *tmpfid;
- }
-
- /* Verify that our path hasn't changed since we started the lookup.
- Record the current index, and verify the path resolves to the
- same fid. If it does, then the path is correct as of this index. */
- cfs_spin_lock(&mdd->mdd_cl.mc_lock);
- pli->pli_currec = mdd->mdd_cl.mc_index;
- cfs_spin_unlock(&mdd->mdd_cl.mc_lock);
- rc = mdd_path2fid(env, mdd, ptr, &pli->pli_fid);
- if (rc) {
- CDEBUG(D_INFO, "mdd_path2fid(%s) failed %d\n", ptr, rc);
- GOTO (out, rc = -EAGAIN);
- }
- if (!lu_fid_eq(&pli->pli_fids[0], &pli->pli_fid)) {
- CDEBUG(D_INFO, "mdd_path2fid(%s) found another FID o="DFID
- " n="DFID"\n", ptr, PFID(&pli->pli_fids[0]),
- PFID(&pli->pli_fid));
- GOTO(out, rc = -EAGAIN);
- }
- ptr++; /* skip leading / */
- memmove(pli->pli_path, ptr, pli->pli_path + pli->pli_pathlen - ptr);
-
- EXIT;
-out:
- if (buf && !IS_ERR(buf) && buf->lb_len > OBD_ALLOC_BIG)
- /* if we vmalloced a large buffer drop it */
- mdd_buf_put(buf);
-
- return rc;
-}
-
-static int mdd_path_historic(const struct lu_env *env,
- struct path_lookup_info *pli)
-{
- return 0;
-}
-
-/* Returns the full path to this fid, as of changelog record recno. */
-static int mdd_path(const struct lu_env *env, struct md_object *obj,
- char *path, int pathlen, __u64 *recno, int *linkno)
-{
- struct path_lookup_info *pli;
- int tries = 3;
- int rc = -EAGAIN;
- ENTRY;
-
- if (pathlen < 3)
- RETURN(-EOVERFLOW);
-
- if (mdd_is_root(mdo2mdd(obj), mdd_object_fid(md2mdd_obj(obj)))) {
- path[0] = '\0';
- RETURN(0);
- }
-
- OBD_ALLOC_PTR(pli);
- if (pli == NULL)
- RETURN(-ENOMEM);
-
- pli->pli_mdd_obj = md2mdd_obj(obj);
- pli->pli_recno = *recno;
- pli->pli_path = path;
- pli->pli_pathlen = pathlen;
- pli->pli_linkno = *linkno;
-
- /* Retry multiple times in case file is being moved */
- while (tries-- && rc == -EAGAIN)
- rc = mdd_path_current(env, pli);
-
- /* For historical path lookup, the current links may not have existed
- * at "recno" time. We must switch over to earlier links/parents
- * by using the changelog records. If the earlier parent doesn't
- * exist, we must search back through the changelog to reconstruct
- * its parents, then check if it exists, etc.
- * We may ignore this problem for the initial implementation and
- * state that an "original" hardlink must still exist for us to find
- * historic path name. */
- if (pli->pli_recno != -1) {
- rc = mdd_path_historic(env, pli);
- } else {
- *recno = pli->pli_currec;
- /* Return next link index to caller */
- *linkno = pli->pli_linkno;
- }
-
- OBD_FREE_PTR(pli);
-
- RETURN (rc);
-}
-
-int mdd_get_flags(const struct lu_env *env, struct mdd_object *obj)
-{
- struct lu_attr *la = &mdd_env_info(env)->mti_la;
- int rc;
-
- ENTRY;
- rc = mdd_la_get(env, obj, la, BYPASS_CAPA);
- if (rc == 0) {
- mdd_flags_xlate(obj, la->la_flags);
- }
- RETURN(rc);
-}
-
-/* get only inode attributes */
-int mdd_iattr_get(const struct lu_env *env, struct mdd_object *mdd_obj,
- struct md_attr *ma)
-{
- int rc = 0;
- ENTRY;
-
- if (ma->ma_valid & MA_INODE)
- RETURN(0);
-
- rc = mdd_la_get(env, mdd_obj, &ma->ma_attr,
- mdd_object_capa(env, mdd_obj));
- if (rc == 0)
- ma->ma_valid |= MA_INODE;
- RETURN(rc);
-}
-
-int mdd_get_default_md(struct mdd_object *mdd_obj, struct lov_mds_md *lmm)
-{
- struct lov_desc *ldesc;
- struct mdd_device *mdd = mdo2mdd(&mdd_obj->mod_obj);
- struct lov_user_md *lum = (struct lov_user_md*)lmm;
- ENTRY;
-
- if (!lum)
- RETURN(0);
-
- ldesc = &mdd->mdd_obd_dev->u.mds.mds_lov_desc;
- LASSERT(ldesc != NULL);
-
- lum->lmm_magic = LOV_MAGIC_V1;
- lum->lmm_object_seq = FID_SEQ_LOV_DEFAULT;
- lum->lmm_pattern = ldesc->ld_pattern;
- lum->lmm_stripe_size = ldesc->ld_default_stripe_size;
- lum->lmm_stripe_count = ldesc->ld_default_stripe_count;
- lum->lmm_stripe_offset = ldesc->ld_default_stripe_offset;
-
- RETURN(sizeof(*lum));
-}
-
-static int is_rootdir(struct mdd_object *mdd_obj)
-{
- const struct mdd_device *mdd_dev = mdd_obj2mdd_dev(mdd_obj);
- const struct lu_fid *fid = mdo2fid(mdd_obj);
-
- return lu_fid_eq(&mdd_dev->mdd_root_fid, fid);
-}
-
-/* get lov EA only */
-static int __mdd_lmm_get(const struct lu_env *env,
- struct mdd_object *mdd_obj, struct md_attr *ma)
-{
- int rc;
- ENTRY;
-
- if (ma->ma_valid & MA_LOV)
- RETURN(0);
-
- rc = mdd_get_md(env, mdd_obj, ma->ma_lmm, &ma->ma_lmm_size,
- XATTR_NAME_LOV);
- if (rc == 0 && (ma->ma_need & MA_LOV_DEF) && is_rootdir(mdd_obj))
- rc = mdd_get_default_md(mdd_obj, ma->ma_lmm);
- if (rc > 0) {
- ma->ma_lmm_size = rc;
- ma->ma_layout_gen = ma->ma_lmm->lmm_layout_gen;
- ma->ma_valid |= MA_LOV | MA_LAY_GEN;
- rc = 0;
- }
- RETURN(rc);
-}
-
-/* get the first parent fid from link EA */
-static int mdd_pfid_get(const struct lu_env *env,
- struct mdd_object *mdd_obj, struct md_attr *ma)
-{
- struct lu_buf *buf;
- struct link_ea_header *leh;
- struct link_ea_entry *lee;
- struct lu_fid *pfid = &ma->ma_pfid;
- ENTRY;
-
- if (ma->ma_valid & MA_PFID)
- RETURN(0);
-
- buf = mdd_links_get(env, mdd_obj);
- if (IS_ERR(buf))
- RETURN(PTR_ERR(buf));
-
- leh = buf->lb_buf;
- lee = (struct link_ea_entry *)(leh + 1);
- memcpy(pfid, &lee->lee_parent_fid, sizeof(*pfid));
- fid_be_to_cpu(pfid, pfid);
- ma->ma_valid |= MA_PFID;
- if (buf->lb_len > OBD_ALLOC_BIG)
- /* if we vmalloced a large buffer drop it */
- mdd_buf_put(buf);
- RETURN(0);
-}
-
-int mdd_lmm_get_locked(const struct lu_env *env, struct mdd_object *mdd_obj,
- struct md_attr *ma)
-{
- int rc;
- ENTRY;
-
- mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
- rc = __mdd_lmm_get(env, mdd_obj, ma);
- mdd_read_unlock(env, mdd_obj);
- RETURN(rc);
-}
-
-/* get lmv EA only*/
-static int __mdd_lmv_get(const struct lu_env *env,
- struct mdd_object *mdd_obj, struct md_attr *ma)
-{
- int rc;
- ENTRY;
-
- if (ma->ma_valid & MA_LMV)
- RETURN(0);
-
- rc = mdd_get_md(env, mdd_obj, ma->ma_lmv, &ma->ma_lmv_size,
- XATTR_NAME_LMV);
- if (rc > 0) {
- ma->ma_valid |= MA_LMV;
- rc = 0;
- }
- RETURN(rc);
-}
-
-static int __mdd_lma_get(const struct lu_env *env, struct mdd_object *mdd_obj,
- struct md_attr *ma)
-{
- struct mdd_thread_info *info = mdd_env_info(env);
- struct lustre_mdt_attrs *lma =
- (struct lustre_mdt_attrs *)info->mti_xattr_buf;
- int lma_size;
- int rc;
- ENTRY;
-
- /* If all needed data are already valid, nothing to do */
- if ((ma->ma_valid & (MA_HSM | MA_SOM)) ==
- (ma->ma_need & (MA_HSM | MA_SOM)))
- RETURN(0);
-
- /* Read LMA from disk EA */
- lma_size = sizeof(info->mti_xattr_buf);
- rc = mdd_get_md(env, mdd_obj, lma, &lma_size, XATTR_NAME_LMA);
- if (rc <= 0)
- RETURN(rc);
-
- /* Useless to check LMA incompatibility because this is already done in
- * osd_ea_fid_get(), and this will fail long before this code is
- * called.
- * So, if we are here, LMA is compatible.
- */
-
- lustre_lma_swab(lma);
-
- /* Swab and copy LMA */
- if (ma->ma_need & MA_HSM) {
- if (lma->lma_compat & LMAC_HSM)
- ma->ma_hsm.mh_flags = lma->lma_flags & HSM_FLAGS_MASK;
- else
- ma->ma_hsm.mh_flags = 0;
- ma->ma_valid |= MA_HSM;
- }
-
- /* Copy SOM */
- if (ma->ma_need & MA_SOM && lma->lma_compat & LMAC_SOM) {
- LASSERT(ma->ma_som != NULL);
- ma->ma_som->msd_ioepoch = lma->lma_ioepoch;
- ma->ma_som->msd_size = lma->lma_som_size;
- ma->ma_som->msd_blocks = lma->lma_som_blocks;
- ma->ma_som->msd_mountid = lma->lma_som_mountid;
- ma->ma_valid |= MA_SOM;
- }
-
- RETURN(0);
-}
-
-int mdd_attr_get_internal(const struct lu_env *env, struct mdd_object *mdd_obj,
- struct md_attr *ma)
-{
- int rc = 0;
- ENTRY;
-
- if (ma->ma_need & MA_INODE)
- rc = mdd_iattr_get(env, mdd_obj, ma);
-
- if (rc == 0 && ma->ma_need & MA_LOV) {
- if (S_ISREG(mdd_object_type(mdd_obj)) ||
- S_ISDIR(mdd_object_type(mdd_obj)))
- rc = __mdd_lmm_get(env, mdd_obj, ma);
- }
- if (rc == 0 && ma->ma_need & MA_PFID && !(ma->ma_valid & MA_LOV)) {
- if (S_ISREG(mdd_object_type(mdd_obj)))
- rc = mdd_pfid_get(env, mdd_obj, ma);
- }
- if (rc == 0 && ma->ma_need & MA_LMV) {
- if (S_ISDIR(mdd_object_type(mdd_obj)))
- rc = __mdd_lmv_get(env, mdd_obj, ma);
- }
- if (rc == 0 && ma->ma_need & (MA_HSM | MA_SOM)) {
- if (S_ISREG(mdd_object_type(mdd_obj)))
- rc = __mdd_lma_get(env, mdd_obj, ma);
- }
-#ifdef CONFIG_FS_POSIX_ACL
- if (rc == 0 && ma->ma_need & MA_ACL_DEF) {
- if (S_ISDIR(mdd_object_type(mdd_obj)))
- rc = mdd_def_acl_get(env, mdd_obj, ma);
- }
-#endif
- CDEBUG(D_INODE, "after getattr rc = %d, ma_valid = "LPX64" ma_lmm=%p\n",
- rc, ma->ma_valid, ma->ma_lmm);
- RETURN(rc);
-}
-
-int mdd_attr_get_internal_locked(const struct lu_env *env,
- struct mdd_object *mdd_obj, struct md_attr *ma)
-{
- int rc;
- int needlock = ma->ma_need &
- (MA_LOV | MA_LMV | MA_ACL_DEF | MA_HSM | MA_SOM | MA_PFID);
-
- if (needlock)
- mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
- rc = mdd_attr_get_internal(env, mdd_obj, ma);
- if (needlock)
- mdd_read_unlock(env, mdd_obj);
- return rc;
-}
-