1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * Lustre Metadata Target (mdt) open/close file handling
7 * Copyright (C) 2002-2006 Cluster File Systems, Inc.
8 * Author: Huang Hua <huanghua@clusterfs.com>
10 * This file is part of the Lustre file system, http://www.lustre.org
11 * Lustre is a trademark of Cluster File Systems, Inc.
13 * You may have signed or agreed to another license before downloading
14 * this software. If so, you are bound by the terms and conditions
15 * of that agreement, and the following does not apply to you. See the
16 * LICENSE file included with this distribution for more information.
18 * If you did not agree to a different license, then this copy of Lustre
19 * is open source software; you can redistribute it and/or modify it
20 * under the terms of version 2 of the GNU General Public License as
21 * published by the Free Software Foundation.
23 * In either case, Lustre is distributed in the hope that it will be
24 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
25 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * license text for more details.
30 # define EXPORT_SYMTAB
32 #define DEBUG_SUBSYSTEM S_MDS
34 #include "mdt_internal.h"
36 /* we do nothing because we do not have refcount now */
37 static void mdt_mfd_get(void *mfdp)
41 /* Create a new mdt_file_data struct, initialize it,
42 * and insert it to global hash table */
43 static struct mdt_file_data *mdt_mfd_new(void)
45 struct mdt_file_data *mfd;
50 INIT_LIST_HEAD(&mfd->mfd_handle.h_link);
51 INIT_LIST_HEAD(&mfd->mfd_list);
52 class_handle_hash(&mfd->mfd_handle, mdt_mfd_get);
54 CERROR("mdt: out of memory\n");
59 /* Find the mfd pointed to by handle in global hash table. */
60 static struct mdt_file_data *mdt_handle2mfd(const struct lustre_handle *handle)
63 LASSERT(handle != NULL);
64 RETURN(class_handle2object(handle->cookie));
68 static void mdt_mfd_free(struct mdt_file_data *mfd)
70 LASSERT(list_empty(&mfd->mfd_handle.h_link));
74 static int mdt_mfd_open(struct mdt_thread_info *info,
76 int flags, int created)
78 struct mdt_export_data *med;
79 struct mdt_file_data *mfd;
80 struct mdt_body *repbody;
81 struct md_attr *ma = &info->mti_attr;
82 struct lu_attr *la = &ma->ma_attr;
83 struct ptlrpc_request *req = mdt_info_req(info);
87 med = &req->rq_export->exp_mdt_data;
88 repbody = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
91 /* we have to get attr & lov ea for this object*/
92 rc = mo_attr_get(info->mti_ctxt, mdt_object_child(o), la);
93 if (rc == 0 && S_ISREG(la->la_mode)) {
94 ma->ma_valid |= MA_INODE;
95 rc = mo_xattr_get(info->mti_ctxt,
101 ma->ma_lmm_size = rc;
103 ma->ma_valid |= MA_LOV;
108 if (!S_ISREG(la->la_mode) &&
109 !S_ISDIR(la->la_mode) &&
110 (req->rq_export->exp_connect_flags & OBD_CONNECT_NODEVOH))
111 /* If client supports this, do not return open handle
112 * for special device nodes */
115 /* FIXME:maybe this can be done earlier? */
116 if (S_ISDIR(la->la_mode)) {
117 if (flags & (MDS_OPEN_CREAT | FMODE_WRITE)) {
118 /* we are trying to create or
119 * write an existing dir. */
122 } else if (flags & MDS_OPEN_DIRECTORY)
127 if (ma->ma_valid & MA_INODE)
128 mdt_pack_attr2body(repbody, la, mdt_object_fid(o));
129 if (ma->ma_lmm_size && ma->ma_valid & MA_LOV) {
130 CERROR("LOVLOV size = %d\n", ma->ma_lmm_size);
131 repbody->eadatasize = ma->ma_lmm_size;
132 if (S_ISDIR(la->la_mode))
133 repbody->valid |= OBD_MD_FLDIREA;
135 repbody->valid |= OBD_MD_FLEASIZE;
138 if (flags & FMODE_WRITE) {
139 /*mds_get_write_access*/
140 } else if (flags & MDS_FMODE_EXEC) {
141 /*mds_deny_write_access*/
146 /* keep a reference on this object for this open,
147 * and is released by mdt_mfd_close() */
148 mdt_object_get(info->mti_ctxt, o);
150 mfd->mfd_mode = flags;
152 mfd->mfd_xid = mdt_info_req(info)->rq_xid;
154 spin_lock(&med->med_open_lock);
155 list_add(&mfd->mfd_list, &med->med_open_head);
156 spin_unlock(&med->med_open_lock);
158 repbody->handle.cookie = mfd->mfd_handle.h_cookie;
165 int mdt_open_by_fid(struct mdt_thread_info* info, const struct lu_fid *fid,
168 struct mdt_object *o;
169 struct lu_attr *la = &info->mti_attr.ma_attr;
173 o = mdt_object_find(info->mti_ctxt, info->mti_mdt, fid);
175 if (mdt_object_exists(info->mti_ctxt, &o->mot_obj.mo_lu)) {
176 if (la->la_flags & MDS_OPEN_EXCL &&
177 la->la_flags & MDS_OPEN_CREAT)
180 rc = mdt_mfd_open(info, o, flags, 0);
183 if (la->la_flags & MDS_OPEN_CREAT) {
184 rc = mo_object_create(info->mti_ctxt,
188 rc = mdt_mfd_open(info, o, flags, 1);
191 mdt_object_put(info->mti_ctxt, o);
198 int mdt_pin(struct mdt_thread_info* info)
200 struct mdt_body *body;
204 rc = req_capsule_pack(&info->mti_pill);
206 body = req_capsule_client_get(&info->mti_pill, &RMF_MDT_BODY);
207 rc = mdt_open_by_fid(info, &body->fid1, body->flags);
212 /* Get an internal lock on the inode number (but not generation) to sync
213 * new inode creation with inode unlink (bug 2029). If child_lockh is NULL
214 * we just get the lock as a barrier to wait for other holders of this lock,
215 * and drop it right away again. */
216 int mdt_lock_new_child(struct mdt_thread_info *info,
217 struct mdt_object *o,
218 struct mdt_lock_handle *child_lockh)
220 struct mdt_lock_handle lockh;
224 if (child_lockh == NULL)
225 child_lockh = &lockh;
227 mdt_lock_handle_init(&lockh);
228 lockh.mlh_mode = LCK_EX;
229 rc = mdt_object_lock(info, o, &lockh, MDS_INODELOCK_UPDATE);
232 CERROR("can not mdt_object_lock: %d\n", rc);
233 else if (child_lockh == &lockh)
234 mdt_object_unlock(info, o, &lockh);
239 int mdt_reint_open(struct mdt_thread_info *info)
241 struct mdt_device *mdt = info->mti_mdt;
242 struct mdt_object *parent;
243 struct mdt_object *child;
244 struct mdt_lock_handle *lh;
245 struct ldlm_reply *ldlm_rep;
246 struct lu_fid *child_fid = &info->mti_tmp_fid1;
247 struct md_attr *ma = &info->mti_attr;
248 struct lu_attr *la = &ma->ma_attr;
251 struct mdt_reint_record *rr = &info->mti_rr;
254 ma->ma_lmm = req_capsule_server_get(&info->mti_pill,
256 ma->ma_lmm_size = req_capsule_get_size(&info->mti_pill,
260 if (strlen(rr->rr_name) == 0) {
261 /* reint partial remote open */
262 RETURN(mdt_open_by_fid(info, rr->rr_fid1, la->la_flags));
265 /* we now have no resent message, so it must be an intent */
266 /*TODO: remove this and add MDS_CHECK_RESENT if resent enabled*/
267 LASSERT(info->mti_pill.rc_fmt == &RQF_LDLM_INTENT_OPEN);
269 ldlm_rep = req_capsule_server_get(&info->mti_pill, &RMF_DLM_REP);
271 intent_set_disposition(ldlm_rep, DISP_LOOKUP_EXECD);
272 lh = &info->mti_lh[MDT_LH_PARENT];
273 lh->mlh_mode = LCK_PW;
274 parent = mdt_object_find_lock(info, rr->rr_fid1, lh,
275 MDS_INODELOCK_UPDATE);
276 if (IS_ERR(parent)) {
277 /* just simulate child not existing */
278 intent_set_disposition(ldlm_rep, DISP_LOOKUP_NEG);
279 GOTO(out, result = PTR_ERR(parent));
282 result = mdo_lookup(info->mti_ctxt, mdt_object_child(parent),
283 rr->rr_name, child_fid);
284 if (result != 0 && result != -ENOENT) {
285 GOTO(out_parent, result);
288 if (result == -ENOENT) {
289 intent_set_disposition(ldlm_rep, DISP_LOOKUP_NEG);
290 if (!(la->la_flags & MDS_OPEN_CREAT))
291 GOTO(out_parent, result);
292 *child_fid = *info->mti_rr.rr_fid2;
294 intent_set_disposition(ldlm_rep, DISP_LOOKUP_POS);
295 if (la->la_flags & MDS_OPEN_EXCL &&
296 la->la_flags & MDS_OPEN_CREAT)
297 GOTO(out_parent, result = -EEXIST);
300 child = mdt_object_find(info->mti_ctxt, mdt, child_fid);
302 GOTO(out_parent, result = PTR_ERR(child));
304 if (result == -ENOENT) {
305 /* not found and with MDS_OPEN_CREAT: let's create it */
306 result = mdo_create(info->mti_ctxt,
307 mdt_object_child(parent),
309 mdt_object_child(child),
312 intent_set_disposition(ldlm_rep, DISP_OPEN_CREATE);
314 GOTO(out_child, result);
319 result = mdt_mfd_open(info, child, la->la_flags, created);
320 intent_set_disposition(ldlm_rep, DISP_OPEN_OPEN);
321 GOTO(finish_open, result);
324 if (result != 0 && created) {
325 mdo_unlink(info->mti_ctxt, mdt_object_child(parent),
326 mdt_object_child(child), rr->rr_name,
330 mdt_object_put(info->mti_ctxt, child);
332 mdt_object_unlock_put(info, parent, lh);
337 int mdt_mfd_close(const struct lu_context *ctxt,
338 struct mdt_file_data *mfd)
342 if (mfd->mfd_mode & FMODE_WRITE) {
343 /*mdt_put_write_access*/
344 } else if (mfd->mfd_mode & MDS_FMODE_EXEC) {
345 /*mdt_allow_write_access*/
348 /* release reference on this object.
349 * it will be destroyed by lower layer if necessary.
351 mdt_object_put(ctxt, mfd->mfd_object);
357 int mdt_close(struct mdt_thread_info *info)
359 struct mdt_export_data *med;
360 struct mdt_file_data *mfd;
364 med = &mdt_info_req(info)->rq_export->exp_mdt_data;
366 spin_lock(&med->med_open_lock);
367 mfd = mdt_handle2mfd(&(info->mti_body->handle));
369 spin_unlock(&med->med_open_lock);
370 CDEBUG(D_INODE, "no handle for file close: fid = "DFID3
371 ": cookie = "LPX64, PFID3(&info->mti_body->fid1),
372 info->mti_body->handle.cookie);
375 class_handle_unhash(&mfd->mfd_handle);
376 list_del_init(&mfd->mfd_list);
377 spin_unlock(&med->med_open_lock);
379 rc = mdt_handle_last_unlink(info, mfd->mfd_object,
380 &RQF_MDS_CLOSE_LAST);
382 rc = mdt_mfd_close(info->mti_ctxt, mfd);
387 int mdt_done_writing(struct mdt_thread_info *info)