Whamcloud - gitweb
LU-6215 llite: handle kernel symlink api changes in 4.2+
[fs/lustre-release.git] / lustre / llite / symlink.c
index a2de898..4b1a9da 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2012, Intel Corporation.
+ * Copyright (c) 2011, 2014, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -40,7 +40,6 @@
 #include <linux/version.h>
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <lustre_lite.h>
 #include "llite_internal.h"
 
 static int ll_readlink_internal(struct inode *inode,
@@ -78,21 +77,25 @@ static int ll_readlink_internal(struct inode *inode,
         ll_finish_md_op_data(op_data);
         if (rc) {
                 if (rc != -ENOENT)
-                        CERROR("inode %lu: rc = %d\n", inode->i_ino, rc);
+                       CERROR("%s: inode "DFID": rc = %d\n",
+                              ll_get_fsname(inode->i_sb, NULL, 0),
+                              PFID(ll_inode2fid(inode)), rc);
                 GOTO (failed, rc);
         }
 
         body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY);
         LASSERT(body != NULL);
-        if ((body->valid & OBD_MD_LINKNAME) == 0) {
-                CERROR("OBD_MD_LINKNAME not set on reply\n");
-                GOTO(failed, rc = -EPROTO);
-        }
+       if ((body->mbo_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);
+       LASSERT(symlen != 0);
+       if (body->mbo_eadatasize != symlen) {
+               CERROR("%s: inode "DFID": symlink length %d not expected %d\n",
+                      ll_get_fsname(inode->i_sb, NULL, 0),
+                      PFID(ll_inode2fid(inode)), body->mbo_eadatasize - 1,
+                      symlen - 1);
                 GOTO(failed, rc = -EPROTO);
         }
 
@@ -100,8 +103,9 @@ static int ll_readlink_internal(struct inode *inode,
         if (*symname == NULL ||
             strnlen(*symname, symlen) != symlen - 1) {
                 /* not full/NULL terminated */
-                CERROR("inode %lu: symlink not NULL terminated string"
-                        "of length %d\n", inode->i_ino, symlen - 1);
+               CERROR("%s: inode "DFID": symlink not NULL terminated string"
+                      "of length %d\n", ll_get_fsname(inode->i_sb, NULL, 0),
+                      PFID(ll_inode2fid(inode)), symlen - 1);
                 GOTO(failed, rc = -EPROTO);
         }
 
@@ -117,34 +121,13 @@ failed:
         RETURN (rc);
 }
 
-static int ll_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
-        struct inode *inode = dentry->d_inode;
-        struct ptlrpc_request *request;
-        char *symname;
-        int rc;
-        ENTRY;
-
-        CDEBUG(D_VFSTRACE, "VFS Op\n");
-
-       ll_inode_size_lock(inode);
-        rc = ll_readlink_internal(inode, &request, &symname);
-        if (rc)
-                GOTO(out, rc);
-
-        rc = vfs_readlink(dentry, buffer, buflen, symname);
- out:
-        ptlrpc_req_finished(request);
-       ll_inode_size_unlock(inode);
-       RETURN(rc);
-}
-
+#ifdef HAVE_SYMLINK_OPS_USE_NAMEIDATA
 static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
        struct ptlrpc_request *request = NULL;
        int rc;
-       char *symname;
+       char *symname = NULL;
        ENTRY;
 
         CDEBUG(D_VFSTRACE, "VFS Op\n");
@@ -172,14 +155,43 @@ static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd)
         */
        RETURN(request);
 }
+#else
+static const char *ll_follow_link(struct dentry *dentry, void **cookie)
+{
+       struct inode *inode = d_inode(dentry);
+       struct ptlrpc_request *request;
+       char *symname;
+       int rc;
+       ENTRY;
+
+       CDEBUG(D_VFSTRACE, "VFS Op\n");
+       ll_inode_size_lock(inode);
+       rc = ll_readlink_internal(inode, &request, &symname);
+       ll_inode_size_unlock(inode);
+       if (rc < 0) {
+               ptlrpc_req_finished(request);
+               return ERR_PTR(rc);
+       }
+
+       /* symname may contain a pointer to the request message buffer,
+        * we delay request releasing until ll_put_link then.
+        */
+       *cookie = request;
+       RETURN(symname);
+}
+#endif /* HAVE_SYMLINK_OPS_USE_NAMEIDATA */
 
+#ifdef HAVE_SYMLINK_OPS_USE_NAMEIDATA
 static void ll_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+#else
+static void ll_put_link(struct inode *unused, void *cookie)
+#endif
 {
        ptlrpc_req_finished(cookie);
 }
 
 struct inode_operations ll_fast_symlink_inode_operations = {
-       .readlink       = ll_readlink,
+       .readlink       = generic_readlink,
        .setattr        = ll_setattr,
        .follow_link    = ll_follow_link,
        .put_link       = ll_put_link,