X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lustre%2Fllite%2Fsymlink.c;h=3056bf5c995c65d74f842f75c5b09b6e524cb800;hb=f98de6c88bbea09960f6019c7ad92a03a2b44913;hp=927d6b00bcba80d5e92210eaeef9449331d3d146;hpb=a4c2aa85752707b2725863c9cce4e924d0cfa9d0;p=fs%2Flustre-release.git diff --git a/lustre/llite/symlink.c b/lustre/llite/symlink.c index 927d6b0..3056bf5 100644 --- a/lustre/llite/symlink.c +++ b/lustre/llite/symlink.c @@ -19,43 +19,77 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include +#include #define DEBUG_SUBSYSTEM S_LLITE #include +#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); - int rc, len = inode->i_size + 1; + struct ll_fid fid; + struct mds_body *body; + int rc, symlen = inode->i_size + 1; ENTRY; *request = NULL; - CHECK_MOUNT_EPOCH(inode); - if (lli->lli_symlink_name) { *symname = lli->lli_symlink_name; CDEBUG(D_INODE, "using cached symlink %s\n", *symname); RETURN(0); } - rc = mdc_getattr(&sbi->ll_mdc_conn, inode->i_ino, S_IFLNK, - OBD_MD_LINKNAME, len, request); + ll_inode2fid(&fid, inode); + rc = mdc_getattr(sbi->ll_mdc_exp, &fid, + OBD_MD_LINKNAME, symlen, request); if (rc) { - CERROR("inode "LPD64": rc = %d\n", inode->i_ino, rc); + CERROR("inode %lu: rc = %d\n", inode->i_ino, rc); RETURN(rc); } - *symname = lustre_msg_buf((*request)->rq_repmsg, 1); + 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); + } + + *symname = lustre_msg_buf ((*request)->rq_repmsg, 1, symlen); + 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); + GOTO (failed, rc = -EPROTO); + } - OBD_ALLOC(lli->lli_symlink_name, len); + OBD_ALLOC(lli->lli_symlink_name, symlen); /* do not return an error if we cannot cache the symlink locally */ if (lli->lli_symlink_name) - memcpy(lli->lli_symlink_name, *symname, len); + memcpy(lli->lli_symlink_name, *symname, symlen); RETURN(0); + + failed: + ptlrpc_req_finished (*request); + RETURN (-EPROTO); } static int ll_readlink(struct dentry *dentry, char *buffer, int buflen) @@ -67,8 +101,7 @@ static int ll_readlink(struct dentry *dentry, char *buffer, int buflen) int rc; ENTRY; - CHECK_MOUNT_EPOCH(inode); - + CDEBUG(D_VFSTRACE, "VFS Op\n"); /* on symlinks lli_open_sem protects lli_symlink_name allocation/data */ down(&lli->lli_open_sem); rc = ll_readlink_internal(inode, &request, &symname); @@ -76,10 +109,9 @@ static int ll_readlink(struct dentry *dentry, char *buffer, int buflen) GOTO(out, rc); rc = vfs_readlink(dentry, buffer, buflen, symname); + ptlrpc_req_finished(request); out: up(&lli->lli_open_sem); - ptlrpc_req_finished(request); - RETURN(rc); } @@ -87,29 +119,42 @@ static int ll_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); + struct lookup_intent *it = ll_nd2it(nd); struct ptlrpc_request *request; - char *symname; int rc; + char *symname; ENTRY; - CHECK_MOUNT_EPOCH(inode); + if (it != NULL) { + int op = it->it_op; + int mode = it->it_create_mode; + + ll_intent_release(it); + it->it_op = op; + it->it_create_mode = mode; + } + CDEBUG(D_VFSTRACE, "VFS Op\n"); down(&lli->lli_open_sem); rc = ll_readlink_internal(inode, &request, &symname); + up(&lli->lli_open_sem); if (rc) GOTO(out, rc); - rc = vfs_follow_link(nd, symname); - out: - up(&lli->lli_open_sem); + rc = vfs_follow_link(nd, symname); ptlrpc_req_finished(request); - + out: RETURN(rc); } -extern int ll_setattr(struct dentry *de, struct iattr *attr); struct inode_operations ll_fast_symlink_inode_operations = { readlink: ll_readlink, setattr: ll_setattr, - follow_link: ll_follow_link + setattr_raw: ll_setattr_raw, + follow_link: ll_follow_link, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + revalidate_it: ll_inode_revalidate_it +#else + getattr_it: ll_getattr +#endif };