Whamcloud - gitweb
Make symlinks actually work:
[fs/lustre-release.git] / lustre / llite / symlink.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *  linux/fs/ext2/symlink.c
4  *
5  * This code is issued under the GNU General Public License.
6  * See the file COPYING in this distribution
7  *
8  * Copyright (C) 1992, 1993, 1994, 1995
9  * Remy Card (card@masi.ibp.fr)
10  * Laboratoire MASI - Institut Blaise Pascal
11  * Universite Pierre et Marie Curie (Paris VI)
12  *
13  *  Copyright (C) 1991, 1992  Linus Torvalds
14  *
15  *  ext2 symlink handling code
16  *
17  * Modified for OBDFS:
18  *  Copyright (C) 1999 Seagate Technology Inc. (author: braam@stelias.com)
19  */
20
21 #include <linux/fs.h>
22 #include <linux/mm.h>
23 #include <linux/stat.h>
24 #include <linux/locks.h>
25
26 #define DEBUG_SUBSYSTEM S_LLITE
27
28 #include <linux/obd_support.h> /* for ENTRY and EXIT only */
29 #include <linux/lustre_lite.h>
30
31 static int ll_readlink(struct dentry *dentry, char *buffer, int buflen)
32 {
33         struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode);
34         struct ptlrpc_request *request = NULL;
35         struct inode *inode = dentry->d_inode;
36         struct ll_inode_info *lli = ll_i2info(inode);
37         int len = inode->i_size + 1;
38         char *symname;
39         int rc;
40         ENTRY;
41
42         /* on symlinks lli_open_sem protects lli_symlink_name allocation/data */
43         down(&lli->lli_open_sem);
44         if (lli->lli_symlink_name) {
45                 symname = lli->lli_symlink_name;
46                 CDEBUG(D_INODE, "using cached symlink %s\n", symname);
47                 GOTO(out_readlink, rc = 0);
48         }
49
50         rc = mdc_getattr(&sbi->ll_mdc_conn, inode->i_ino, S_IFLNK,
51                          OBD_MD_LINKNAME, len, &request);
52
53         if (rc) {
54                 CERROR("inode %d readlink: rc = %ld\n", rc, inode->i_ino);
55                 GOTO(out_readlink_sem, rc);
56         }
57
58         symname = lustre_msg_buf(request->rq_repmsg, 1);
59
60         OBD_ALLOC(lli->lli_symlink_name, len);
61         /* do not return an error if we cannot cache the symlink locally */
62         if (lli->lli_symlink_name)
63                 memcpy(lli->lli_symlink_name, symname, len);
64
65 out_readlink:
66         rc = vfs_readlink(dentry, buffer, buflen, symname);
67
68 out_readlink_sem:
69         up(&lli->lli_open_sem);
70         ptlrpc_free_req(request);
71
72         RETURN(rc);
73 }
74
75 extern int ll_setattr(struct dentry *de, struct iattr *attr);
76 struct inode_operations ll_fast_symlink_inode_operations = {
77         readlink:       ll_readlink,
78         setattr:        ll_setattr
79 };