X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Fsymlink.c;h=365910fb6c38e58bfd1aae6b7045fea4f8679b3e;hb=fbf5870b9848929d352460f1f005b79c0b5ccc5a;hp=e401266ed261345ea841f4b6ac03f32759fed7ec;hpb=bd1b99d7caa6ab2b7c771524af9178a3da69eeab;p=fs%2Flustre-release.git diff --git a/lustre/llite/symlink.c b/lustre/llite/symlink.c index e401266..365910f 100644 --- a/lustre/llite/symlink.c +++ b/lustre/llite/symlink.c @@ -1,22 +1,37 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * Copyright (c) 2002 Cluster File Systems, Inc. + * GPL HEADER START * - * This file is part of Lustre, http://www.lustre.org. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Lustre is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. * - * Lustre is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). * - * You should have received a copy of the GNU General Public License - * along with Lustre; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Use is subject to license terms. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. */ #include @@ -26,7 +41,7 @@ #include #define DEBUG_SUBSYSTEM S_LLITE -#include +#include #include "llite_internal.h" static int ll_readlink_internal(struct inode *inode, @@ -34,9 +49,9 @@ static int ll_readlink_internal(struct inode *inode, { 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; + int rc, symlen = i_size_read(inode) + 1; + struct mdt_body *body; + struct obd_capa *oc; ENTRY; *request = NULL; @@ -47,55 +62,58 @@ static int ll_readlink_internal(struct inode *inode, RETURN(0); } - ll_inode2fid(&fid, inode); - rc = mdc_getattr(sbi->ll_mdc_exp, &fid, - OBD_MD_LINKNAME, symlen, request); + oc = ll_mdscapa_get(inode); + rc = md_getattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, + OBD_MD_LINKNAME, symlen, request); + capa_put(oc); if (rc) { - CERROR("inode %lu: rc = %d\n", inode->i_ino, rc); - RETURN(rc); + if (rc != -ENOENT) + CERROR("inode %lu: rc = %d\n", inode->i_ino, rc); + GOTO (failed, rc); } - body = lustre_msg_buf ((*request)->rq_repmsg, 0, sizeof (*body)); - LASSERT (body != NULL); - LASSERT_REPSWABBED (*request, 0); - + 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); + CERROR("OBD_MD_LINKNAME not set on reply\n"); + GOTO(failed, rc = -EPROTO); } - - LASSERT (symlen != 0); + + LASSERT(symlen != 0); if (body->eadatasize != symlen) { - CERROR ("inode %lu: symlink length %d not expected %d\n", + CERROR("inode %lu: symlink length %d not expected %d\n", inode->i_ino, body->eadatasize - 1, symlen - 1); - GOTO (failed, rc = -EPROTO); + GOTO(failed, rc = -EPROTO); } - *symname = lustre_msg_buf ((*request)->rq_repmsg, 1, symlen); + *symname = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_MD); if (*symname == NULL || - strnlen (*symname, symlen) != symlen - 1) { + strnlen(*symname, symlen) != symlen - 1) { /* not full/NULL terminated */ - CERROR ("inode %lu: symlink not NULL terminated string" + CERROR("inode %lu: symlink not NULL terminated string" "of length %d\n", inode->i_ino, symlen - 1); - GOTO (failed, rc = -EPROTO); + GOTO(failed, rc = -EPROTO); } OBD_ALLOC(lli->lli_symlink_name, symlen); /* do not return an error if we cannot cache the symlink locally */ - if (lli->lli_symlink_name) + if (lli->lli_symlink_name) { memcpy(lli->lli_symlink_name, *symname, symlen); + ptlrpc_req_finished (*request); + *request = NULL; + *symname = lli->lli_symlink_name; + } RETURN(0); failed: ptlrpc_req_finished (*request); - RETURN (-EPROTO); + RETURN (rc); } static int ll_readlink(struct dentry *dentry, char *buffer, int buflen) { struct inode *inode = dentry->d_inode; - struct ll_inode_info *lli = ll_i2info(inode); struct ptlrpc_request *request; char *symname; int rc; @@ -103,7 +121,7 @@ static int ll_readlink(struct dentry *dentry, char *buffer, int buflen) CDEBUG(D_VFSTRACE, "VFS Op\n"); /* on symlinks lli_open_sem protects lli_symlink_name allocation/data */ - down(&lli->lli_open_sem); + ll_inode_size_lock(inode, 0); rc = ll_readlink_internal(inode, &request, &symname); if (rc) GOTO(out, rc); @@ -111,20 +129,29 @@ static int ll_readlink(struct dentry *dentry, char *buffer, int buflen) rc = vfs_readlink(dentry, buffer, buflen, symname); ptlrpc_req_finished(request); out: - up(&lli->lli_open_sem); + ll_inode_size_unlock(inode, 0); RETURN(rc); } -static int ll_follow_link(struct dentry *dentry, struct nameidata *nd) +#ifdef HAVE_COOKIE_FOLLOW_LINK +# define LL_FOLLOW_LINK_RETURN_TYPE void * +#else +# define LL_FOLLOW_LINK_RETURN_TYPE int +#endif + +static LL_FOLLOW_LINK_RETURN_TYPE ll_follow_link(struct dentry *dentry, + struct nameidata *nd) { struct inode *inode = dentry->d_inode; - struct ll_inode_info *lli = ll_i2info(inode); +#ifdef HAVE_VFS_INTENT_PATCHES struct lookup_intent *it = ll_nd2it(nd); +#endif struct ptlrpc_request *request; int rc; char *symname; ENTRY; +#ifdef HAVE_VFS_INTENT_PATCHES if (it != NULL) { int op = it->it_op; int mode = it->it_create_mode; @@ -133,28 +160,81 @@ static int ll_follow_link(struct dentry *dentry, struct nameidata *nd) it->it_op = op; it->it_create_mode = mode; } +#endif CDEBUG(D_VFSTRACE, "VFS Op\n"); - down(&lli->lli_open_sem); +#if THREAD_SIZE < 8192 + /* + * We set the limits recursive symlink to 5 + * instead of default 8 when kernel has 4k stack + * to prevent stack overflow. + */ + if (current->link_count >= 5) { + rc = -ELOOP; + GOTO(out_release, rc); + } +#endif + ll_inode_size_lock(inode, 0); rc = ll_readlink_internal(inode, &request, &symname); - up(&lli->lli_open_sem); - if (rc) + ll_inode_size_unlock(inode, 0); + if (rc) { +#if THREAD_SIZE < 8192 +out_release: +#endif + path_release(nd); /* Kernel assumes that ->follow_link() + releases nameidata on error */ GOTO(out, rc); + } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)) + rc = vfs_follow_link(nd, symname); +#else +#ifdef HAVE_COOKIE_FOLLOW_LINK + nd_set_link(nd, symname); + /* @symname may contain a pointer to the request message buffer, + we delay request releasing until ll_put_link then. */ + RETURN(request); +#else + if (request != NULL) { + /* falling back to recursive follow link if the request + * needs to be cleaned up still. */ rc = vfs_follow_link(nd, symname); + GOTO(out, rc); + } + nd_set_link(nd, symname); + RETURN(0); +#endif +#endif +out: ptlrpc_req_finished(request); - out: +#ifdef HAVE_COOKIE_FOLLOW_LINK + RETURN(ERR_PTR(rc)); +#else RETURN(rc); +#endif +} + +#ifdef HAVE_COOKIE_FOLLOW_LINK +static void ll_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) +{ + ptlrpc_req_finished(cookie); } +#endif struct inode_operations ll_fast_symlink_inode_operations = { .readlink = ll_readlink, .setattr = ll_setattr, +#ifdef HAVE_VFS_INTENT_PATCHES .setattr_raw = ll_setattr_raw, +#endif .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 +#ifdef HAVE_COOKIE_FOLLOW_LINK + .put_link = ll_put_link, #endif + .getattr = ll_getattr, + .permission = ll_inode_permission, + .setxattr = ll_setxattr, + .getxattr = ll_getxattr, + .listxattr = ll_listxattr, + .removexattr = ll_removexattr, };