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 static int ll_nfs_test_inode(struct inode
*inode
, void *opaque
)
63 return lu_fid_eq(&ll_i2info(inode
)->lli_fid
,
64 (struct lu_fid
*)opaque
);
67 struct inode
*search_inode_for_lustre(struct super_block
*sb
,
68 const struct lu_fid
*fid
)
70 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
71 struct ptlrpc_request
*req
= NULL
;
72 struct inode
*inode
= NULL
;
74 unsigned long hash
= cl_fid_build_ino(fid
,
75 ll_need_32bit_api(sbi
));
76 struct md_op_data
*op_data
;
80 CDEBUG(D_INFO
, "searching inode for:(%lu,"DFID
")\n", hash
, PFID(fid
));
82 inode
= ilookup5(sb
, hash
, ll_nfs_test_inode
, (void *)fid
);
86 rc
= ll_get_max_mdsize(sbi
, &eadatalen
);
90 /* Because inode is NULL, ll_prep_md_op_data can not
91 * be used here. So we allocate op_data ourselves */
92 OBD_ALLOC_PTR(op_data
);
94 return ERR_PTR(-ENOMEM
);
96 op_data
->op_fid1
= *fid
;
97 op_data
->op_mode
= eadatalen
;
98 op_data
->op_valid
= OBD_MD_FLEASIZE
;
100 /* mds_fid2dentry ignores f_type */
101 rc
= md_getattr(sbi
->ll_md_exp
, op_data
, &req
);
102 OBD_FREE_PTR(op_data
);
104 CERROR("can't get object attrs, fid "DFID
", rc %d\n",
108 rc
= ll_prep_inode(&inode
, req
, sb
, NULL
);
109 ptlrpc_req_finished(req
);
116 struct lustre_nfs_fid
{
117 struct lu_fid lnf_child
;
118 struct lu_fid lnf_parent
;
121 static struct dentry
*
122 ll_iget_for_nfs(struct super_block
*sb
, struct lu_fid
*fid
, struct lu_fid
*parent
)
125 struct dentry
*result
;
128 CDEBUG(D_INFO
, "Get dentry for fid: "DFID
"\n", PFID(fid
));
129 if (!fid_is_sane(fid
))
130 RETURN(ERR_PTR(-ESTALE
));
132 inode
= search_inode_for_lustre(sb
, fid
);
134 RETURN(ERR_PTR(PTR_ERR(inode
)));
136 if (is_bad_inode(inode
)) {
137 /* we didn't find the right inode.. */
139 RETURN(ERR_PTR(-ESTALE
));
143 * It is an anonymous dentry without OST objects created yet.
144 * We have to find the parent to tell MDS how to init lov objects.
146 if (S_ISREG(inode
->i_mode
) && !ll_i2info(inode
)->lli_has_smd
&&
148 struct ll_inode_info
*lli
= ll_i2info(inode
);
150 spin_lock(&lli
->lli_lock
);
151 lli
->lli_pfid
= *parent
;
152 spin_unlock(&lli
->lli_lock
);
155 result
= d_obtain_alias(inode
);
159 ll_dops_init(result
, 1, 0);
164 #define LUSTRE_NFS_FID 0x97
167 * \a connectable - is nfsd will connect himself or this should be done
170 * The return value is file handle type:
171 * 1 -- contains child file handle;
172 * 2 -- contains child file handle and parent file handle;
175 static int ll_encode_fh(struct inode
*inode
, __u32
*fh
, int *plen
,
176 struct inode
*parent
)
178 struct lustre_nfs_fid
*nfs_fid
= (void *)fh
;
181 CDEBUG(D_INFO
, "encoding for (%lu,"DFID
") maxlen=%d minlen=%d\n",
182 inode
->i_ino
, PFID(ll_inode2fid(inode
)), *plen
,
183 (int)sizeof(struct lustre_nfs_fid
));
185 if (*plen
< sizeof(struct lustre_nfs_fid
) / 4)
188 nfs_fid
->lnf_child
= *ll_inode2fid(inode
);
189 nfs_fid
->lnf_parent
= *ll_inode2fid(parent
);
190 *plen
= sizeof(struct lustre_nfs_fid
) / 4;
192 RETURN(LUSTRE_NFS_FID
);
195 static int ll_nfs_get_name_filldir(void *cookie
, const char *name
, int namelen
,
196 loff_t hash
, u64 ino
, unsigned type
)
198 /* It is hack to access lde_fid for comparison with lgd_fid.
199 * So the input 'name' must be part of the 'lu_dirent'. */
200 struct lu_dirent
*lde
= container_of0(name
, struct lu_dirent
, lde_name
);
201 struct ll_getname_data
*lgd
= cookie
;
204 fid_le_to_cpu(&fid
, &lde
->lde_fid
);
205 if (lu_fid_eq(&fid
, &lgd
->lgd_fid
)) {
206 memcpy(lgd
->lgd_name
, name
, namelen
);
207 lgd
->lgd_name
[namelen
] = 0;
210 return lgd
->lgd_found
;
213 static int ll_get_name(struct dentry
*dentry
, char *name
,
214 struct dentry
*child
)
216 struct inode
*dir
= dentry
->d_inode
;
217 struct ll_getname_data lgd
;
222 if (!dir
|| !S_ISDIR(dir
->i_mode
))
223 GOTO(out
, rc
= -ENOTDIR
);
226 GOTO(out
, rc
= -EINVAL
);
229 lgd
.lgd_fid
= ll_i2info(child
->d_inode
)->lli_fid
;
232 mutex_lock(&dir
->i_mutex
);
233 rc
= ll_dir_read(dir
, &offset
, &lgd
, ll_nfs_get_name_filldir
);
234 mutex_unlock(&dir
->i_mutex
);
235 if (!rc
&& !lgd
.lgd_found
)
243 static struct dentry
*ll_fh_to_dentry(struct super_block
*sb
, struct fid
*fid
,
244 int fh_len
, int fh_type
)
246 struct lustre_nfs_fid
*nfs_fid
= (struct lustre_nfs_fid
*)fid
;
248 if (fh_type
!= LUSTRE_NFS_FID
)
249 RETURN(ERR_PTR(-EPROTO
));
251 RETURN(ll_iget_for_nfs(sb
, &nfs_fid
->lnf_child
, &nfs_fid
->lnf_parent
));
254 static struct dentry
*ll_fh_to_parent(struct super_block
*sb
, struct fid
*fid
,
255 int fh_len
, int fh_type
)
257 struct lustre_nfs_fid
*nfs_fid
= (struct lustre_nfs_fid
*)fid
;
259 if (fh_type
!= LUSTRE_NFS_FID
)
260 RETURN(ERR_PTR(-EPROTO
));
262 RETURN(ll_iget_for_nfs(sb
, &nfs_fid
->lnf_parent
, NULL
));
265 static struct dentry
*ll_get_parent(struct dentry
*dchild
)
267 struct ptlrpc_request
*req
= NULL
;
268 struct inode
*dir
= dchild
->d_inode
;
269 struct ll_sb_info
*sbi
;
270 struct dentry
*result
= NULL
;
271 struct mdt_body
*body
;
272 static char dotdot
[] = "..";
273 struct md_op_data
*op_data
;
278 LASSERT(dir
&& S_ISDIR(dir
->i_mode
));
280 sbi
= ll_s2sbi(dir
->i_sb
);
282 CDEBUG(D_INFO
, "getting parent for (%lu,"DFID
")\n",
283 dir
->i_ino
, PFID(ll_inode2fid(dir
)));
285 rc
= ll_get_max_mdsize(sbi
, &lmmsize
);
289 op_data
= ll_prep_md_op_data(NULL
, dir
, NULL
, dotdot
,
290 strlen(dotdot
), lmmsize
,
291 LUSTRE_OPC_ANY
, NULL
);
293 RETURN((void *)op_data
);
295 rc
= md_getattr_name(sbi
->ll_md_exp
, op_data
, &req
);
296 ll_finish_md_op_data(op_data
);
298 CERROR("failure %d inode %lu get parent\n", rc
, dir
->i_ino
);
301 body
= req_capsule_server_get(&req
->rq_pill
, &RMF_MDT_BODY
);
302 LASSERT(body
->valid
& OBD_MD_FLID
);
304 CDEBUG(D_INFO
, "parent for "DFID
" is "DFID
"\n",
305 PFID(ll_inode2fid(dir
)), PFID(&body
->fid1
));
307 result
= ll_iget_for_nfs(dir
->i_sb
, &body
->fid1
, NULL
);
309 ptlrpc_req_finished(req
);
313 struct export_operations lustre_export_operations
= {
314 .get_parent
= ll_get_parent
,
315 .encode_fh
= ll_encode_fh
,
316 .get_name
= ll_get_name
,
317 .fh_to_dentry
= ll_fh_to_dentry
,
318 .fh_to_parent
= ll_fh_to_parent
,