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 "../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;
54 __u32 key
= key1
+ (key0
^ (*name
++ * 7152373));
64 void get_uuid2fsid(const char *name
, int len
, __kernel_fsid_t
*fsid
)
66 __u64 key
= 0, key0
= 0x12a3fe2d, key1
= 0x37abe8f9;
69 key
= key1
+ (key0
^ (*name
++ * 7152373));
70 if (key
& 0x8000000000000000ULL
)
71 key
-= 0x7fffffffffffffffULL
;
77 fsid
->val
[1] = key
>> 32;
80 static int ll_nfs_test_inode(struct inode
*inode
, void *opaque
)
82 return lu_fid_eq(&ll_i2info(inode
)->lli_fid
, opaque
);
85 struct inode
*search_inode_for_lustre(struct super_block
*sb
,
86 const struct lu_fid
*fid
)
88 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
89 struct ptlrpc_request
*req
= NULL
;
90 struct inode
*inode
= NULL
;
92 unsigned long hash
= cl_fid_build_ino(fid
,
93 ll_need_32bit_api(sbi
));
94 struct md_op_data
*op_data
;
97 CDEBUG(D_INFO
, "searching inode for:(%lu,"DFID
")\n", hash
, PFID(fid
));
99 inode
= ilookup5(sb
, hash
, ll_nfs_test_inode
, (void *)fid
);
103 rc
= ll_get_default_mdsize(sbi
, &eadatalen
);
107 /* Because inode is NULL, ll_prep_md_op_data can not
108 * be used here. So we allocate op_data ourselves */
109 op_data
= kzalloc(sizeof(*op_data
), GFP_NOFS
);
111 return ERR_PTR(-ENOMEM
);
113 op_data
->op_fid1
= *fid
;
114 op_data
->op_mode
= eadatalen
;
115 op_data
->op_valid
= OBD_MD_FLEASIZE
;
117 /* mds_fid2dentry ignores f_type */
118 rc
= md_getattr(sbi
->ll_md_exp
, op_data
, &req
);
121 CERROR("can't get object attrs, fid "DFID
", rc %d\n",
125 rc
= ll_prep_inode(&inode
, req
, sb
, NULL
);
126 ptlrpc_req_finished(req
);
133 struct lustre_nfs_fid
{
134 struct lu_fid lnf_child
;
135 struct lu_fid lnf_parent
;
138 static struct dentry
*
139 ll_iget_for_nfs(struct super_block
*sb
, struct lu_fid
*fid
, struct lu_fid
*parent
)
142 struct dentry
*result
;
144 CDEBUG(D_INFO
, "Get dentry for fid: "DFID
"\n", PFID(fid
));
145 if (!fid_is_sane(fid
))
146 return ERR_PTR(-ESTALE
);
148 inode
= search_inode_for_lustre(sb
, fid
);
150 return ERR_CAST(inode
);
152 if (is_bad_inode(inode
)) {
153 /* we didn't find the right inode.. */
155 return ERR_PTR(-ESTALE
);
159 * It is an anonymous dentry without OST objects created yet.
160 * We have to find the parent to tell MDS how to init lov objects.
162 if (S_ISREG(inode
->i_mode
) && !ll_i2info(inode
)->lli_has_smd
&&
164 struct ll_inode_info
*lli
= ll_i2info(inode
);
166 spin_lock(&lli
->lli_lock
);
167 lli
->lli_pfid
= *parent
;
168 spin_unlock(&lli
->lli_lock
);
171 /* N.B. d_obtain_alias() drops inode ref on error */
172 result
= d_obtain_alias(inode
);
177 #define LUSTRE_NFS_FID 0x97
180 * \a connectable - is nfsd will connect himself or this should be done
183 * The return value is file handle type:
184 * 1 -- contains child file handle;
185 * 2 -- contains child file handle and parent file handle;
188 static int ll_encode_fh(struct inode
*inode
, __u32
*fh
, int *plen
,
189 struct inode
*parent
)
191 struct lustre_nfs_fid
*nfs_fid
= (void *)fh
;
193 CDEBUG(D_INFO
, "encoding for (%lu,"DFID
") maxlen=%d minlen=%d\n",
194 inode
->i_ino
, PFID(ll_inode2fid(inode
)), *plen
,
195 (int)sizeof(struct lustre_nfs_fid
));
197 if (*plen
< sizeof(struct lustre_nfs_fid
) / 4)
200 nfs_fid
->lnf_child
= *ll_inode2fid(inode
);
201 nfs_fid
->lnf_parent
= *ll_inode2fid(parent
);
202 *plen
= sizeof(struct lustre_nfs_fid
) / 4;
204 return LUSTRE_NFS_FID
;
207 static int ll_nfs_get_name_filldir(struct dir_context
*ctx
, const char *name
,
208 int namelen
, loff_t hash
, u64 ino
,
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
=
215 container_of(ctx
, struct ll_getname_data
, ctx
);
218 fid_le_to_cpu(&fid
, &lde
->lde_fid
);
219 if (lu_fid_eq(&fid
, &lgd
->lgd_fid
)) {
220 memcpy(lgd
->lgd_name
, name
, namelen
);
221 lgd
->lgd_name
[namelen
] = 0;
224 return lgd
->lgd_found
;
227 static int ll_get_name(struct dentry
*dentry
, char *name
,
228 struct dentry
*child
)
230 struct inode
*dir
= d_inode(dentry
);
232 struct ll_getname_data lgd
= {
234 .lgd_fid
= ll_i2info(d_inode(child
))->lli_fid
,
235 .ctx
.actor
= ll_nfs_get_name_filldir
,
238 if (!dir
|| !S_ISDIR(dir
->i_mode
)) {
249 rc
= ll_dir_read(dir
, &lgd
.ctx
);
251 if (!rc
&& !lgd
.lgd_found
)
257 static struct dentry
*ll_fh_to_dentry(struct super_block
*sb
, struct fid
*fid
,
258 int fh_len
, int fh_type
)
260 struct lustre_nfs_fid
*nfs_fid
= (struct lustre_nfs_fid
*)fid
;
262 if (fh_type
!= LUSTRE_NFS_FID
)
263 return ERR_PTR(-EPROTO
);
265 return ll_iget_for_nfs(sb
, &nfs_fid
->lnf_child
, &nfs_fid
->lnf_parent
);
268 static struct dentry
*ll_fh_to_parent(struct super_block
*sb
, struct fid
*fid
,
269 int fh_len
, int fh_type
)
271 struct lustre_nfs_fid
*nfs_fid
= (struct lustre_nfs_fid
*)fid
;
273 if (fh_type
!= LUSTRE_NFS_FID
)
274 return ERR_PTR(-EPROTO
);
276 return ll_iget_for_nfs(sb
, &nfs_fid
->lnf_parent
, NULL
);
279 static struct dentry
*ll_get_parent(struct dentry
*dchild
)
281 struct ptlrpc_request
*req
= NULL
;
282 struct inode
*dir
= d_inode(dchild
);
283 struct ll_sb_info
*sbi
;
284 struct dentry
*result
= NULL
;
285 struct mdt_body
*body
;
286 static char dotdot
[] = "..";
287 struct md_op_data
*op_data
;
291 LASSERT(dir
&& S_ISDIR(dir
->i_mode
));
293 sbi
= ll_s2sbi(dir
->i_sb
);
295 CDEBUG(D_INFO
, "getting parent for (%lu,"DFID
")\n",
296 dir
->i_ino
, PFID(ll_inode2fid(dir
)));
298 rc
= ll_get_default_mdsize(sbi
, &lmmsize
);
302 op_data
= ll_prep_md_op_data(NULL
, dir
, NULL
, dotdot
,
303 strlen(dotdot
), lmmsize
,
304 LUSTRE_OPC_ANY
, NULL
);
306 return (void *)op_data
;
308 rc
= md_getattr_name(sbi
->ll_md_exp
, op_data
, &req
);
309 ll_finish_md_op_data(op_data
);
311 CERROR("failure %d inode %lu get parent\n", rc
, dir
->i_ino
);
314 body
= req_capsule_server_get(&req
->rq_pill
, &RMF_MDT_BODY
);
315 LASSERT(body
->valid
& OBD_MD_FLID
);
317 CDEBUG(D_INFO
, "parent for "DFID
" is "DFID
"\n",
318 PFID(ll_inode2fid(dir
)), PFID(&body
->fid1
));
320 result
= ll_iget_for_nfs(dir
->i_sb
, &body
->fid1
, NULL
);
322 ptlrpc_req_finished(req
);
326 struct export_operations lustre_export_operations
= {
327 .get_parent
= ll_get_parent
,
328 .encode_fh
= ll_encode_fh
,
329 .get_name
= ll_get_name
,
330 .fh_to_dentry
= ll_fh_to_dentry
,
331 .fh_to_parent
= ll_fh_to_parent
,