/**
* Parse linkea content to extract information about a given hardlink
*
- * \param[in] ldata - Initialized linkea data
- * \param[in] linkno - Link identifier
- * \param[out] gpout - Destination structure to fill with linkno,
- * parent FID and entry name
- * \param[in] size - Size of the gp_name buffer in gpout
+ * \param[in] ldata - Initialized linkea data
+ * \param[in] linkno - Link identifier
+ * \param[out] parent_fid - The entry's parent FID
+ * \param[out] ln - Entry name destination buffer
*
* \retval 0 on success
* \retval Appropriate negative error code on failure
*/
static int ll_linkea_decode(struct linkea_data *ldata, unsigned int linkno,
- struct getparent *gpout, size_t name_size)
+ struct lu_fid *parent_fid, struct lu_name *ln)
{
unsigned int idx;
- struct lu_name ln;
int rc;
ENTRY;
RETURN(-ENODATA);
linkea_first_entry(ldata);
- idx = 0;
- while (ldata->ld_lee != NULL) {
- linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, &ln,
- &gpout->gp_fid);
+ for (idx = 0; ldata->ld_lee != NULL; idx++) {
+ linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, ln,
+ parent_fid);
if (idx == linkno)
break;
linkea_next_entry(ldata);
- idx++;
}
if (idx < linkno)
RETURN(-ENODATA);
- if (ln.ln_namelen >= name_size)
- RETURN(-EOVERFLOW);
-
- gpout->gp_linkno = linkno;
- strlcpy(gpout->gp_name, ln.ln_name, name_size);
RETURN(0);
}
struct inode *inode = file->f_dentry->d_inode;
struct linkea_data *ldata;
struct lu_buf buf = LU_BUF_NULL;
- struct getparent *gpout;
+ struct lu_name ln;
+ struct lu_fid parent_fid;
__u32 linkno;
__u32 name_size;
- size_t out_size;
int rc;
ENTRY;
if (rc < 0)
GOTO(ldata_free, rc);
- out_size = sizeof(*gpout) + name_size;
- OBD_ALLOC(gpout, out_size);
- if (gpout == NULL)
- GOTO(lb_free, rc = -ENOMEM);
-
- if (copy_from_user(gpout, arg, sizeof(*gpout)))
- GOTO(gp_free, rc = -EFAULT);
-
rc = ll_getxattr(dentry, XATTR_NAME_LINK, buf.lb_buf, buf.lb_len);
if (rc < 0)
- GOTO(gp_free, rc);
+ GOTO(lb_free, rc);
- rc = ll_linkea_decode(ldata, linkno, gpout, name_size);
+ rc = ll_linkea_decode(ldata, linkno, &parent_fid, &ln);
if (rc < 0)
- GOTO(gp_free, rc);
+ GOTO(lb_free, rc);
+
+ if (ln.ln_namelen >= name_size)
+ GOTO(lb_free, rc = -EOVERFLOW);
+
+ if (copy_to_user(&arg->gp_fid, &parent_fid, sizeof(arg->gp_fid)))
+ GOTO(lb_free, rc = -EFAULT);
+
+ if (copy_to_user(&arg->gp_name, ln.ln_name, ln.ln_namelen))
+ GOTO(lb_free, rc = -EFAULT);
- if (copy_to_user(arg, gpout, out_size))
- GOTO(gp_free, rc = -EFAULT);
+ if (put_user('\0', arg->gp_name + ln.ln_namelen))
+ GOTO(lb_free, rc = -EFAULT);
-gp_free:
- OBD_FREE(gpout, out_size);
lb_free:
lu_buf_free(&buf);
ldata_free: