+#include <linux/smp_lock.h>
+#include <linux/version.h>
+#define DEBUG_SUBSYSTEM S_LLITE
+
+#include <linux/lustre_lite.h>
+#include "llite_internal.h"
+
+static int ll_readlink_internal(struct inode *inode,
+ struct ptlrpc_request **request, char **symname)
+{
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ struct ll_fid fid;
+ struct mds_body *body;
+ int rc, symlen = inode->i_size + 1;
+ ENTRY;
+
+ *request = NULL;
+
+ if (lli->lli_symlink_name) {
+ *symname = lli->lli_symlink_name;
+ CDEBUG(D_INODE, "using cached symlink %s\n", *symname);
+ RETURN(0);
+ }
+
+ ll_inode2fid(&fid, inode);
+ rc = mdc_getattr(sbi->ll_mdc_exp, &fid,
+ OBD_MD_LINKNAME, symlen, request);
+ if (rc) {
+ CERROR("inode %lu: rc = %d\n", inode->i_ino, rc);
+ RETURN(rc);
+ }
+
+ body = lustre_msg_buf ((*request)->rq_repmsg, 0, sizeof (*body));
+ LASSERT (body != NULL);
+ LASSERT_REPSWABBED (*request, 0);
+
+ if ((body->valid & OBD_MD_LINKNAME) == 0) {
+ CERROR ("OBD_MD_LINKNAME not set on reply\n");
+ GOTO (failed, rc = -EPROTO);
+ }
+
+ LASSERT (symlen != 0);
+ if (body->eadatasize != symlen) {
+ CERROR ("inode %lu: symlink length %d not expected %d\n",
+ inode->i_ino, body->eadatasize - 1, symlen - 1);
+ GOTO (failed, rc = -EPROTO);
+ }