4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/lustre/llite/llite_nfs.c
38 * NFS export of Lustre Light File System
40 * Author: Yury Umanets <umka@clusterfs.com>
41 * Author: Huang Hua <huanghua@clusterfs.com>
44 #define DEBUG_SUBSYSTEM S_LLITE
45 #include <lustre_lite.h>
46 #include "llite_internal.h"
47 #include <linux/exportfs.h>
49 __u32
get_uuid2int(const char *name
, int len
)
51 __u32 key0
= 0x12a3fe2d, key1
= 0x37abe8f9;
53 __u32 key
= key1
+ (key0
^ (*name
++ * 7152373));
54 if (key
& 0x80000000) key
-= 0x7fffffff;
61 void get_uuid2fsid(const char *name
, int len
, __kernel_fsid_t
*fsid
)
63 __u64 key
= 0, key0
= 0x12a3fe2d, key1
= 0x37abe8f9;
66 key
= key1
+ (key0
^ (*name
++ * 7152373));
67 if (key
& 0x8000000000000000ULL
)
68 key
-= 0x7fffffffffffffffULL
;
74 fsid
->val
[1] = key
>> 32;
77 static int ll_nfs_test_inode(struct inode
*inode
, void *opaque
)
79 return lu_fid_eq(&ll_i2info(inode
)->lli_fid
,
80 (struct lu_fid
*)opaque
);
83 struct inode
*search_inode_for_lustre(struct super_block
*sb
,
84 const struct lu_fid
*fid
)
86 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
87 struct ptlrpc_request
*req
= NULL
;
88 struct inode
*inode
= NULL
;
90 unsigned long hash
= cl_fid_build_ino(fid
,
91 ll_need_32bit_api(sbi
));
92 struct md_op_data
*op_data
;
95 CDEBUG(D_INFO
, "searching inode for:(%lu,"DFID
")\n", hash
, PFID(fid
));
97 inode
= ilookup5(sb
, hash
, ll_nfs_test_inode
, (void *)fid
);
101 rc
= ll_get_max_mdsize(sbi
, &eadatalen
);
105 /* Because inode is NULL, ll_prep_md_op_data can not
106 * be used here. So we allocate op_data ourselves */
107 OBD_ALLOC_PTR(op_data
);
109 return ERR_PTR(-ENOMEM
);
111 op_data
->op_fid1
= *fid
;
112 op_data
->op_mode
= eadatalen
;
113 op_data
->op_valid
= OBD_MD_FLEASIZE
;
115 /* mds_fid2dentry ignores f_type */
116 rc
= md_getattr(sbi
->ll_md_exp
, op_data
, &req
);
117 OBD_FREE_PTR(op_data
);
119 CERROR("can't get object attrs, fid "DFID
", rc %d\n",
123 rc
= ll_prep_inode(&inode
, req
, sb
, NULL
);
124 ptlrpc_req_finished(req
);
131 struct lustre_nfs_fid
{
132 struct lu_fid lnf_child
;
133 struct lu_fid lnf_parent
;
136 static struct dentry
*
137 ll_iget_for_nfs(struct super_block
*sb
, struct lu_fid
*fid
, struct lu_fid
*parent
)
140 struct dentry
*result
;
142 CDEBUG(D_INFO
, "Get dentry for fid: "DFID
"\n", PFID(fid
));
143 if (!fid_is_sane(fid
))
144 RETURN(ERR_PTR(-ESTALE
));
146 inode
= search_inode_for_lustre(sb
, fid
);
148 RETURN(ERR_CAST(inode
));
150 if (is_bad_inode(inode
)) {
151 /* we didn't find the right inode.. */
153 RETURN(ERR_PTR(-ESTALE
));
157 * It is an anonymous dentry without OST objects created yet.
158 * We have to find the parent to tell MDS how to init lov objects.
160 if (S_ISREG(inode
->i_mode
) && !ll_i2info(inode
)->lli_has_smd
&&
162 struct ll_inode_info
*lli
= ll_i2info(inode
);
164 spin_lock(&lli
->lli_lock
);
165 lli
->lli_pfid
= *parent
;
166 spin_unlock(&lli
->lli_lock
);
169 result
= d_obtain_alias(inode
);
173 ll_dops_init(result
, 1, 0);
178 #define LUSTRE_NFS_FID 0x97
181 * \a connectable - is nfsd will connect himself or this should be done
184 * The return value is file handle type:
185 * 1 -- contains child file handle;
186 * 2 -- contains child file handle and parent file handle;
189 static int ll_encode_fh(struct inode
*inode
, __u32
*fh
, int *plen
,
190 struct inode
*parent
)
192 struct lustre_nfs_fid
*nfs_fid
= (void *)fh
;
194 CDEBUG(D_INFO
, "encoding for (%lu,"DFID
") maxlen=%d minlen=%d\n",
195 inode
->i_ino
, PFID(ll_inode2fid(inode
)), *plen
,
196 (int)sizeof(struct lustre_nfs_fid
));
198 if (*plen
< sizeof(struct lustre_nfs_fid
) / 4)
201 nfs_fid
->lnf_child
= *ll_inode2fid(inode
);
202 nfs_fid
->lnf_parent
= *ll_inode2fid(parent
);
203 *plen
= sizeof(struct lustre_nfs_fid
) / 4;
205 RETURN(LUSTRE_NFS_FID
);
208 static int ll_nfs_get_name_filldir(void *cookie
, const char *name
, int namelen
,
209 loff_t hash
, u64 ino
, unsigned type
)
211 /* It is hack to access lde_fid for comparison with lgd_fid.
212 * So the input 'name' must be part of the 'lu_dirent'. */
213 struct lu_dirent
*lde
= container_of0(name
, struct lu_dirent
, lde_name
);
214 struct ll_getname_data
*lgd
= cookie
;
217 fid_le_to_cpu(&fid
, &lde
->lde_fid
);
218 if (lu_fid_eq(&fid
, &lgd
->lgd_fid
)) {
219 memcpy(lgd
->lgd_name
, name
, namelen
);
220 lgd
->lgd_name
[namelen
] = 0;
223 return lgd
->lgd_found
;
226 static int ll_get_name(struct dentry
*dentry
, char *name
,
227 struct dentry
*child
)
229 struct inode
*dir
= dentry
->d_inode
;
231 struct ll_getname_data lgd
= {
233 .lgd_fid
= ll_i2info(child
->d_inode
)->lli_fid
,
234 .ctx
.actor
= ll_nfs_get_name_filldir
,
237 if (!dir
|| !S_ISDIR(dir
->i_mode
))
238 GOTO(out
, rc
= -ENOTDIR
);
241 GOTO(out
, rc
= -EINVAL
);
243 mutex_lock(&dir
->i_mutex
);
244 rc
= ll_dir_read(dir
, &lgd
.ctx
);
245 mutex_unlock(&dir
->i_mutex
);
246 if (!rc
&& !lgd
.lgd_found
)
252 static struct dentry
*ll_fh_to_dentry(struct super_block
*sb
, struct fid
*fid
,
253 int fh_len
, int fh_type
)
255 struct lustre_nfs_fid
*nfs_fid
= (struct lustre_nfs_fid
*)fid
;
257 if (fh_type
!= LUSTRE_NFS_FID
)
258 RETURN(ERR_PTR(-EPROTO
));
260 RETURN(ll_iget_for_nfs(sb
, &nfs_fid
->lnf_child
, &nfs_fid
->lnf_parent
));
263 static struct dentry
*ll_fh_to_parent(struct super_block
*sb
, struct fid
*fid
,
264 int fh_len
, int fh_type
)
266 struct lustre_nfs_fid
*nfs_fid
= (struct lustre_nfs_fid
*)fid
;
268 if (fh_type
!= LUSTRE_NFS_FID
)
269 RETURN(ERR_PTR(-EPROTO
));
271 RETURN(ll_iget_for_nfs(sb
, &nfs_fid
->lnf_parent
, NULL
));
274 static struct dentry
*ll_get_parent(struct dentry
*dchild
)
276 struct ptlrpc_request
*req
= NULL
;
277 struct inode
*dir
= dchild
->d_inode
;
278 struct ll_sb_info
*sbi
;
279 struct dentry
*result
= NULL
;
280 struct mdt_body
*body
;
281 static char dotdot
[] = "..";
282 struct md_op_data
*op_data
;
286 LASSERT(dir
&& S_ISDIR(dir
->i_mode
));
288 sbi
= ll_s2sbi(dir
->i_sb
);
290 CDEBUG(D_INFO
, "getting parent for (%lu,"DFID
")\n",
291 dir
->i_ino
, PFID(ll_inode2fid(dir
)));
293 rc
= ll_get_max_mdsize(sbi
, &lmmsize
);
297 op_data
= ll_prep_md_op_data(NULL
, dir
, NULL
, dotdot
,
298 strlen(dotdot
), lmmsize
,
299 LUSTRE_OPC_ANY
, NULL
);
301 RETURN((void *)op_data
);
303 rc
= md_getattr_name(sbi
->ll_md_exp
, op_data
, &req
);
304 ll_finish_md_op_data(op_data
);
306 CERROR("failure %d inode %lu get parent\n", rc
, dir
->i_ino
);
309 body
= req_capsule_server_get(&req
->rq_pill
, &RMF_MDT_BODY
);
310 LASSERT(body
->valid
& OBD_MD_FLID
);
312 CDEBUG(D_INFO
, "parent for "DFID
" is "DFID
"\n",
313 PFID(ll_inode2fid(dir
)), PFID(&body
->fid1
));
315 result
= ll_iget_for_nfs(dir
->i_sb
, &body
->fid1
, NULL
);
317 ptlrpc_req_finished(req
);
321 struct export_operations lustre_export_operations
= {
322 .get_parent
= ll_get_parent
,
323 .encode_fh
= ll_encode_fh
,
324 .get_name
= ll_get_name
,
325 .fh_to_dentry
= ll_fh_to_dentry
,
326 .fh_to_parent
= ll_fh_to_parent
,