Whamcloud - gitweb
LU-3285 lvbo: pass lock as parameter to lvbo_update()
[fs/lustre-release.git] / lustre / mdt / mdt_lvb.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 021110-1307, USA
20  *
21  * GPL HEADER END
22  */
23 /*
24  * Copyright (c) 2012, 2015, Intel Corporation.
25  * Use is subject to license terms.
26  *
27  * lustre/mdt/mdt_lvb.c
28  *
29  * Author: Jinshan Xiong <jinshan.xiong@intel.com>
30  */
31
32 #define DEBUG_SUBSYSTEM S_MDS
33
34 #include "mdt_internal.h"
35
36 /* Called with res->lr_lvb_sem held */
37 static int mdt_lvbo_init(struct ldlm_resource *res)
38 {
39         if (IS_LQUOTA_RES(res)) {
40                 struct mdt_device       *mdt;
41
42                 mdt = ldlm_res_to_ns(res)->ns_lvbp;
43                 if (mdt->mdt_qmt_dev == NULL)
44                         return 0;
45
46                 /* call lvbo init function of quota master */
47                 return qmt_hdls.qmth_lvbo_init(mdt->mdt_qmt_dev, res);
48         }
49
50         return 0;
51 }
52
53 static int mdt_lvbo_update(struct ldlm_resource *res,
54                            struct ldlm_lock *lock,
55                            struct ptlrpc_request *req,
56                            int increase_only)
57 {
58         if (IS_LQUOTA_RES(res)) {
59                 struct mdt_device       *mdt;
60
61                 mdt = ldlm_res_to_ns(res)->ns_lvbp;
62                 if (mdt->mdt_qmt_dev == NULL)
63                         return 0;
64
65                 /* call lvbo update function of quota master */
66                 return qmt_hdls.qmth_lvbo_update(mdt->mdt_qmt_dev, res, req,
67                                                  increase_only);
68         }
69
70         return 0;
71 }
72
73
74 static int mdt_lvbo_size(struct ldlm_lock *lock)
75 {
76         struct mdt_device *mdt;
77
78         /* resource on server side never changes. */
79         mdt = ldlm_res_to_ns(lock->l_resource)->ns_lvbp;
80         LASSERT(mdt != NULL);
81
82         if (IS_LQUOTA_RES(lock->l_resource)) {
83                 if (mdt->mdt_qmt_dev == NULL)
84                         return 0;
85
86                 /* call lvbo size function of quota master */
87                 return qmt_hdls.qmth_lvbo_size(mdt->mdt_qmt_dev, lock);
88         }
89
90         if (ldlm_has_layout(lock))
91                 return mdt->mdt_max_mdsize;
92
93         return 0;
94 }
95
96 static int mdt_lvbo_fill(struct ldlm_lock *lock, void *lvb, int lvblen)
97 {
98         struct lu_env env;
99         struct mdt_thread_info *info;
100         struct mdt_device *mdt;
101         struct lu_fid *fid;
102         struct mdt_object *obj = NULL;
103         struct md_object *child = NULL;
104         int rc;
105         ENTRY;
106
107         mdt = ldlm_lock_to_ns(lock)->ns_lvbp;
108         if (IS_LQUOTA_RES(lock->l_resource)) {
109                 if (mdt->mdt_qmt_dev == NULL)
110                         RETURN(0);
111
112                 /* call lvbo fill function of quota master */
113                 rc = qmt_hdls.qmth_lvbo_fill(mdt->mdt_qmt_dev, lock, lvb,
114                                              lvblen);
115                 RETURN(rc);
116         }
117
118         /* Only fill layout if layout lock is granted */
119         if (!ldlm_has_layout(lock) || lock->l_granted_mode != lock->l_req_mode)
120                 RETURN(0);
121
122         /* layout lock will be granted to client, fill in lvb with layout */
123
124         /* XXX create an env to talk to mdt stack. We should get this env from
125          * ptlrpc_thread->t_env. */
126         rc = lu_env_init(&env, LCT_MD_THREAD);
127         /* Likely ENOMEM */
128         if (rc)
129                 RETURN(rc);
130
131         info = lu_context_key_get(&env.le_ctx, &mdt_thread_key);
132         /* Likely ENOMEM */
133         if (info == NULL)
134                 GOTO(out, rc = -ENOMEM);
135
136         memset(info, 0, sizeof *info);
137         info->mti_env = &env;
138         info->mti_exp = lock->l_export;
139         info->mti_mdt = mdt;
140
141         /* XXX get fid by resource id. why don't include fid in ldlm_resource */
142         fid = &info->mti_tmp_fid2;
143         fid_extract_from_res_name(fid, &lock->l_resource->lr_name);
144
145         obj = mdt_object_find(&env, info->mti_mdt, fid);
146         if (IS_ERR(obj))
147                 GOTO(out, rc = PTR_ERR(obj));
148
149         if (!mdt_object_exists(obj) || mdt_object_remote(obj))
150                 GOTO(out, rc = -ENOENT);
151
152         child = mdt_object_child(obj);
153
154         /* get the length of lsm */
155         rc = mo_xattr_get(&env, child, &LU_BUF_NULL, XATTR_NAME_LOV);
156         if (rc < 0)
157                 GOTO(out, rc);
158
159         if (rc > 0) {
160                 struct lu_buf *lmm = NULL;
161
162                 if (lvblen < rc) {
163                         CERROR("%s: expected %d actual %d.\n",
164                                 mdt_obd_name(mdt), rc, lvblen);
165                         GOTO(out, rc = -ERANGE);
166                 }
167
168                 lmm = &info->mti_buf;
169                 lmm->lb_buf = lvb;
170                 lmm->lb_len = rc;
171
172                 rc = mo_xattr_get(&env, child, lmm, XATTR_NAME_LOV);
173                 if (rc < 0)
174                         GOTO(out, rc);
175         }
176
177 out:
178         if (obj != NULL && !IS_ERR(obj))
179                 mdt_object_put(&env, obj);
180         lu_env_fini(&env);
181         RETURN(rc < 0 ? 0 : rc);
182 }
183
184 static int mdt_lvbo_free(struct ldlm_resource *res)
185 {
186         if (IS_LQUOTA_RES(res)) {
187                 struct mdt_device       *mdt;
188
189                 mdt = ldlm_res_to_ns(res)->ns_lvbp;
190                 if (mdt->mdt_qmt_dev == NULL)
191                         return 0;
192
193                 /* call lvbo free function of quota master */
194                 return qmt_hdls.qmth_lvbo_free(mdt->mdt_qmt_dev, res);
195         }
196
197         return 0;
198 }
199
200 struct ldlm_valblock_ops mdt_lvbo = {
201         .lvbo_init      = mdt_lvbo_init,
202         .lvbo_update    = mdt_lvbo_update,
203         .lvbo_size      = mdt_lvbo_size,
204         .lvbo_fill      = mdt_lvbo_fill,
205         .lvbo_free      = mdt_lvbo_free
206 };