X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Fsymlink.c;h=d65220b4c302997fdab9508082f0c3f0ac692a7a;hb=560f935c10c1aef980b5717b5882a0e0f2a6c2a5;hp=83c41f448c975c3aafe88d982f943b1a29e73fb7;hpb=00102f342959b094f035b618c0b7acf477de35b4;p=fs%2Flustre-release.git diff --git a/lustre/llite/symlink.c b/lustre/llite/symlink.c index 83c41f4..d65220b 100644 --- a/lustre/llite/symlink.c +++ b/lustre/llite/symlink.c @@ -1,52 +1,115 @@ -/* - * linux/fs/ext2/symlink.c +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: * - * This code is issued under the GNU General Public License. - * See the file COPYING in this distribution + * Copyright (c) 2002 Cluster File Systems, Inc. * - * Copyright (C) 1992, 1993, 1994, 1995 - * Remy Card (card@masi.ibp.fr) - * Laboratoire MASI - Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) + * This file is part of Lustre, http://www.lustre.org. * - * from + * 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. * - * linux/fs/minix/symlink.c + * 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. * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * ext2 symlink handling code - * - * Modified for OBDFS: - * Copyright (C) 1999 Seagate Technology Inc. (author: braam@stelias.com) + * 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. */ -#include -#include -#include -#include +#define DEBUG_SUBSYSTEM S_LLITE + +#include + +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; + 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); + if (rc) { + CERROR("inode "LPD64": rc = %d\n", inode->i_ino, rc); + RETURN(rc); + } + + *symname = lustre_msg_buf((*request)->rq_repmsg, 1); -#define DEBUG_SUBSYSTEM S_LLIGHT + OBD_ALLOC(lli->lli_symlink_name, len); + /* do not return an error if we cannot cache the symlink locally */ + if (lli->lli_symlink_name) + memcpy(lli->lli_symlink_name, *symname, len); -#include /* for ENTRY and EXIT only */ -#include + RETURN(0); +} -static int ll_fast_readlink(struct dentry *dentry, char *buffer, int buflen) +static int ll_readlink(struct dentry *dentry, char *buffer, int buflen) { - char *s = ll_i2info(dentry->d_inode)->lli_inline; - return vfs_readlink(dentry, buffer, buflen, s); + struct inode *inode = dentry->d_inode; + struct ll_inode_info *lli = ll_i2info(inode); + struct ptlrpc_request *request; + char *symname; + int rc; + ENTRY; + + CHECK_MOUNT_EPOCH(inode); + + /* on symlinks lli_open_sem protects lli_symlink_name allocation/data */ + down(&lli->lli_open_sem); + rc = ll_readlink_internal(inode, &request, &symname); + if (rc) + GOTO(out, rc); + + rc = vfs_readlink(dentry, buffer, buflen, symname); + out: + up(&lli->lli_open_sem); + ptlrpc_free_req(request); + + RETURN(rc); } -static int ll_fast_follow_link(struct dentry *dentry, struct nameidata *nd) +static int ll_follow_link(struct dentry *dentry, struct nameidata *nd) { - char *s = ll_i2info(dentry->d_inode)->lli_inline; - return vfs_follow_link(nd, s); + struct inode *inode = dentry->d_inode; + struct ll_inode_info *lli = ll_i2info(inode); + struct ptlrpc_request *request; + char *symname; + int rc; + ENTRY; + + CHECK_MOUNT_EPOCH(inode); + + down(&lli->lli_open_sem); + rc = ll_readlink_internal(inode, &request, &symname); + if (rc) + GOTO(out, rc); + + rc = vfs_follow_link(nd, symname); + out: + up(&lli->lli_open_sem); + ptlrpc_free_req(request); + + RETURN(rc); } extern int ll_setattr(struct dentry *de, struct iattr *attr); struct inode_operations ll_fast_symlink_inode_operations = { - readlink: ll_fast_readlink, - follow_link: ll_fast_follow_link, - setattr: ll_setattr + readlink: ll_readlink, + setattr: ll_setattr, + follow_link: ll_follow_link }; -