Whamcloud - gitweb
Branch b1_8
[fs/lustre-release.git] / lustre / llite / llite_nfs.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/llite/llite_nfs.c
37  *
38  * NFS export of Lustre Light File System
39  */
40
41 #define DEBUG_SUBSYSTEM S_LLITE
42 #include <lustre_lite.h>
43 #include "llite_internal.h"
44 #ifdef HAVE_LINUX_EXPORTFS_H
45 #include <linux/exportfs.h>
46 #endif
47
48 __u32 get_uuid2int(const char *name, int len)
49 {
50         __u32 key0 = 0x12a3fe2d, key1 = 0x37abe8f9;
51         while (len--) {
52                 __u32 key = key1 + (key0 ^ (*name++ * 7152373));
53                 if (key & 0x80000000) key -= 0x7fffffff;
54                 key1 = key0;
55                 key0 = key;
56         }
57         return (key0 << 1);
58 }
59
60 #if THREAD_SIZE >= 8192 /* see bug 17630 */
61
62 static int ll_nfs_test_inode(struct inode *inode, void *opaque)
63 {
64         struct ll_fid *iid = opaque;
65
66         if (inode->i_ino == iid->id && inode->i_generation == iid->generation)
67                 return 1;
68
69         return 0;
70 }
71
72 static struct inode * search_inode_for_lustre(struct super_block *sb,
73                                               struct ll_fid *iid)
74 {
75         struct ptlrpc_request *req = NULL;
76         struct ll_sb_info *sbi = ll_s2sbi(sb);
77         unsigned long valid = 0;
78         int eadatalen = 0, rc;
79         struct inode *inode = NULL;
80         ENTRY;
81
82         inode = ILOOKUP(sb, iid->id, ll_nfs_test_inode, iid);
83
84         if (inode)
85                 RETURN(inode);
86
87         rc = ll_get_max_mdsize(sbi, &eadatalen);
88         if (rc)
89                 RETURN(ERR_PTR(rc));
90
91         valid |= OBD_MD_FLEASIZE;
92
93         /* mds_fid2dentry is ignore f_type */
94         rc = mdc_getattr(sbi->ll_mdc_exp, iid, valid, eadatalen, &req);
95         if (rc) {
96                 CERROR("failure %d inode "LPU64"\n", rc, iid->id);
97                 RETURN(ERR_PTR(rc));
98         }
99
100         rc = ll_prep_inode(sbi->ll_osc_exp, &inode, req, REPLY_REC_OFF, sb);
101         if (rc) {
102                 ptlrpc_req_finished(req);
103                 RETURN(ERR_PTR(rc));
104         }
105         ptlrpc_req_finished(req);
106
107         RETURN(inode);
108 }
109
110 static struct dentry *ll_iget_for_nfs(struct super_block *sb,
111                                       struct ll_fid *iid)
112 {
113         struct inode *inode;
114         struct dentry *result;
115         ENTRY;
116
117         if (iid->id == 0)
118                 RETURN(ERR_PTR(-ESTALE));
119
120         inode = search_inode_for_lustre(sb, iid);
121         if (IS_ERR(inode))
122                 RETURN(ERR_PTR(PTR_ERR(inode)));
123
124         if (is_bad_inode(inode) ||
125             (iid->generation && inode->i_generation != iid->generation)) {
126                 /* we didn't find the right inode.. */
127                 CERROR("Inode %lu, Bad count: %lu %d or version  %u %u\n",
128                        inode->i_ino, (unsigned long)inode->i_nlink,
129                        atomic_read(&inode->i_count), inode->i_generation,
130                        iid->generation);
131                 iput(inode);
132                 RETURN(ERR_PTR(-ESTALE));
133         }
134
135         result = d_obtain_alias(inode);
136         if (!result) {
137                 iput(inode);
138                 RETURN(ERR_PTR(-ENOMEM));
139         }
140         ll_dops_init(result, 1);
141
142         RETURN(result);
143 }
144
145 #define LUSTRE_NFS_FID                0x94
146
147 struct lustre_nfs_fid {
148         struct ll_fid   child;
149         struct ll_fid   parent;
150         umode_t         mode;
151 };
152
153 /* plen is in 32 bit units!
154  * The return value is file handle type:
155  * 1 -- contains child file handle;
156  * 2 -- contains child file handle and parent file handle;
157  * 255 -- error.
158  */
159 static int ll_encode_fh(struct dentry *de, __u32 *fh, int *plen,
160                         int connectable)
161 {
162         struct inode *inode = de->d_inode;
163         struct inode *parent = de->d_parent->d_inode;
164         struct lustre_nfs_fid *nfs_fid = (void *)fh;
165         ENTRY;
166
167         CDEBUG(D_INFO, "encoding for (%lu) maxlen=%d minlen=%u\n",
168               inode->i_ino, *plen*4,
169               (int)sizeof(struct lustre_nfs_fid));
170
171         if (*plen*4 < sizeof(struct lustre_nfs_fid))
172                 RETURN(255);
173
174         ll_inode2fid(&nfs_fid->child, inode);
175         ll_inode2fid(&nfs_fid->parent, parent);
176
177         nfs_fid->mode = (S_IFMT & inode->i_mode);
178         *plen = sizeof(struct lustre_nfs_fid)/4;
179
180         RETURN(LUSTRE_NFS_FID);
181 }
182
183 #ifdef HAVE_FH_TO_DENTRY
184 static struct dentry *ll_fh_to_dentry(struct super_block *sb, struct fid *fid,
185                                       int fh_len, int fh_type)
186 {
187         struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid;
188
189         if (fh_type != LUSTRE_NFS_FID)
190                 RETURN(ERR_PTR(-EINVAL));
191
192         RETURN(ll_iget_for_nfs(sb, &nfs_fid->child));
193 }
194 static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid,
195                                       int fh_len, int fh_type)
196 {
197         struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid;
198
199         if (fh_type != LUSTRE_NFS_FID)
200                 RETURN(ERR_PTR(-EINVAL));
201         RETURN(ll_iget_for_nfs(sb, &nfs_fid->parent));
202 }
203
204 #else
205 /*
206  * This length is counted as amount of __u32,
207  *  It is composed of a fid and a mode
208  */
209 static struct dentry *ll_decode_fh(struct super_block *sb, __u32 *fh, int fh_len,
210                                      int fh_type,
211                                      int (*acceptable)(void *, struct dentry *),
212                                      void *context)
213 {
214         struct lustre_nfs_fid *nfs_fid = (void *)fh;
215         struct dentry *entry;
216         ENTRY;
217
218         CDEBUG(D_INFO, "decoding for "LPU64" fh_len=%d fh_type=%x\n",
219                 nfs_fid->child.id, fh_len, fh_type);
220
221         if (fh_type != LUSTRE_NFS_FID)
222                   RETURN(ERR_PTR(-ESTALE));
223
224         entry = sb->s_export_op->find_exported_dentry(sb, &nfs_fid->child,
225                                                       &nfs_fid->parent,
226                                                       acceptable, context);
227         RETURN(entry);
228 }
229
230
231 struct dentry *ll_get_dentry(struct super_block *sb, void *data)
232 {
233         struct lustre_nfs_fid *fid = data;
234         ENTRY;
235
236         RETURN(ll_iget_for_nfs(sb, &fid->child));
237
238 }
239
240 #endif
241
242 struct dentry *ll_get_parent(struct dentry *dchild)
243 {
244         struct ptlrpc_request *req = NULL;
245         struct inode *dir = dchild->d_inode;
246         struct ll_sb_info *sbi;
247         struct dentry *result = NULL;
248         struct ll_fid fid;
249         struct mds_body *body;
250         char dotdot[] = "..";
251         int  rc = 0;
252         ENTRY;
253
254         LASSERT(dir && S_ISDIR(dir->i_mode));
255
256         sbi = ll_s2sbi(dir->i_sb);
257
258         fid.id = (__u64)dir->i_ino;
259         fid.generation = dir->i_generation;
260         fid.f_type = S_IFDIR;
261
262         rc = mdc_getattr_name(sbi->ll_mdc_exp, &fid, dotdot, strlen(dotdot) + 1,
263                               0, 0, &req);
264         if (rc) {
265                 CERROR("failure %d inode %lu get parent\n", rc, dir->i_ino);
266                 return ERR_PTR(rc);
267         }
268         body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof (*body));
269
270         LASSERT((body->valid & OBD_MD_FLGENER) && (body->valid & OBD_MD_FLID));
271         fid.id = body->ino;
272         fid.generation = body->generation;
273         result = ll_iget_for_nfs(dir->i_sb, &fid);
274
275         if (IS_ERR(result))
276                 rc = PTR_ERR(result);
277
278         ptlrpc_req_finished(req);
279         if (rc)
280                 return ERR_PTR(rc);
281         RETURN(result);
282 }
283
284 struct export_operations lustre_export_operations = {
285         .encode_fh  = ll_encode_fh,
286         .get_parent = ll_get_parent,
287 #ifdef HAVE_FH_TO_DENTRY
288         .fh_to_dentry = ll_fh_to_dentry,
289         .fh_to_parent = ll_fh_to_parent,
290 #else
291         .get_dentry = ll_get_dentry,
292         .decode_fh  = ll_decode_fh,
293 #endif
294 };
295 #endif /* THREAD_SIZE >= 8192 */