Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / quota / quota_check.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/quota/quota_check.c
5  *
6  *  Copyright (c) 2005 Cluster File Systems, Inc.
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   No redistribution or use is permitted outside of Cluster File Systems, Inc.
11  *
12  */
13 #ifndef EXPORT_SYMTAB
14 # define EXPORT_SYMTAB
15 #endif
16 #define DEBUG_SUBSYSTEM S_MDS
17
18 #ifdef __KERNEL__
19 # include <linux/version.h>
20 # include <linux/module.h>
21 # include <linux/init.h>
22 # include <linux/fs.h>
23 # include <linux/jbd.h>
24 # include <linux/ext3_fs.h>
25 # include <linux/smp_lock.h>
26 # include <linux/buffer_head.h>
27 # include <linux/workqueue.h>
28 # include <linux/mount.h>
29 #else /* __KERNEL__ */
30 # include <liblustre.h>
31 #endif
32
33 #include <obd_class.h>
34 #include <lustre_mds.h>
35 #include <lustre_dlm.h>
36 #include <lustre_cfg.h>
37 #include <obd_ost.h>
38 #include <lustre_fsfilt.h>
39 #include <lustre_quota.h>
40 #include "quota_internal.h"
41
42 #ifdef __KERNEL__
43 static int target_quotacheck_callback(struct obd_export *exp,
44                                       struct obd_quotactl *oqctl)
45 {
46         struct ptlrpc_request *req;
47         struct obd_quotactl *body;
48         int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*oqctl) };
49         ENTRY;
50
51         req = ptlrpc_prep_req(exp->exp_imp_reverse, LUSTRE_OBD_VERSION,
52                               OBD_QC_CALLBACK, 2, size, NULL);
53         if (!req)
54                 RETURN(-ENOMEM);
55
56         body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
57         *body = *oqctl;
58
59         ptlrpc_req_set_repsize(req, 1, NULL);
60
61         rc = ptlrpc_queue_wait(req);
62         ptlrpc_req_finished(req);
63
64         RETURN(rc);
65 }
66
67 static int target_quotacheck_thread(void *data)
68 {
69         struct quotacheck_thread_args *qta = data;
70         struct obd_export *exp;
71         struct obd_device *obd;
72         struct obd_quotactl *oqctl;
73         struct lvfs_run_ctxt saved;
74         int rc;
75
76         ptlrpc_daemonize("quotacheck");
77
78         exp = qta->qta_exp;
79         obd = exp->exp_obd;
80         oqctl = &qta->qta_oqctl;
81
82         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
83
84         rc = fsfilt_quotacheck(obd, qta->qta_sb, oqctl);
85         if (rc)
86                 CERROR("%s: fsfilt_quotacheck: %d\n", obd->obd_name, rc);
87
88         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
89
90         rc = target_quotacheck_callback(exp, oqctl);
91
92         atomic_inc(qta->qta_sem);
93
94         OBD_FREE_PTR(qta);
95         return rc;
96 }
97
98 int target_quota_check(struct obd_export *exp, struct obd_quotactl *oqctl)
99 {
100         struct obd_device *obd = exp->exp_obd;
101         struct obd_device_target *obt = &obd->u.obt;
102         struct quotacheck_thread_args *qta;
103         int rc = 0;
104         ENTRY;
105
106         if (!atomic_dec_and_test(&obt->obt_quotachecking)) {
107                 CDEBUG(D_INFO, "other people are doing quotacheck\n");
108                 GOTO(out, rc = -EBUSY);
109         }
110
111         OBD_ALLOC_PTR(qta);
112         if (!qta)
113                 GOTO(out, rc = -ENOMEM);
114
115         qta->qta_exp = exp;
116         qta->qta_oqctl = *oqctl;
117         qta->qta_sb = obt->obt_sb;
118         qta->qta_sem = &obt->obt_quotachecking;
119
120         if (!strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME)) {
121                 /* quota master */
122                 rc = init_admin_quotafiles(obd, &qta->qta_oqctl);
123                 if (rc) {
124                         CERROR("init_admin_quotafiles failed: %d\n", rc);
125                         OBD_FREE_PTR(qta);
126                         GOTO(out, rc);
127                 }
128         }
129
130         rc = kernel_thread(target_quotacheck_thread, qta, CLONE_VM|CLONE_FILES);
131         if (rc >= 0) {
132                 CDEBUG(D_INFO, "%s: target_quotacheck_thread: %d\n",
133                        obd->obd_name, rc);
134                 RETURN(0);
135         }
136
137         CERROR("%s: error starting quotacheck_thread: %d\n",
138                obd->obd_name, rc);
139         OBD_FREE_PTR(qta);
140 out:
141         atomic_inc(&obt->obt_quotachecking);
142         RETURN(rc);
143 }
144
145 #endif /* __KERNEL__ */
146
147 int client_quota_check(struct obd_export *exp, struct obd_quotactl *oqctl)
148 {
149         struct client_obd *cli = &exp->exp_obd->u.cli;
150         struct ptlrpc_request *req;
151         struct obd_quotactl *body;
152         int size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
153         int ver, opc, rc;
154         ENTRY;
155
156         if (!strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_MDC_NAME)) {
157                 ver = LUSTRE_MDS_VERSION;
158                 opc = MDS_QUOTACHECK;
159         } else if (!strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
160                 ver = LUSTRE_OST_VERSION;
161                 opc = OST_QUOTACHECK;
162         } else {
163                 RETURN(-EINVAL);
164         }
165
166         req = ptlrpc_prep_req(class_exp2cliimp(exp), ver, opc, 2, size, NULL);
167         if (!req)
168                 GOTO(out, rc = -ENOMEM);
169
170         body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
171         *body = *oqctl;
172
173         ptlrpc_req_set_repsize(req, 1, NULL);
174
175         /* the next poll will find -ENODATA, that means quotacheck is
176          * going on */
177         cli->cl_qchk_stat = -ENODATA;
178         rc = ptlrpc_queue_wait(req);
179         if (rc)
180                 cli->cl_qchk_stat = rc;
181 out:
182         ptlrpc_req_finished(req);
183         RETURN(rc);
184 }
185
186 int client_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk)
187 {
188         struct client_obd *cli = &exp->exp_obd->u.cli;
189         int rc;
190         ENTRY;
191
192         rc = cli->cl_qchk_stat;
193
194         /* the client is not the previous one */
195         if (rc == CL_NOT_QUOTACHECKED)
196                 rc = -EINTR;
197
198         qchk->obd_uuid = cli->cl_target_uuid;
199         /* FIXME change strncmp to strcmp and save the strlen op */
200         if (strncmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME,
201             strlen(LUSTRE_OSC_NAME)))
202                 memcpy(qchk->obd_type, LUSTRE_OST_NAME,
203                        strlen(LUSTRE_OST_NAME));
204         else if (strncmp(exp->exp_obd->obd_type->typ_name, LUSTRE_MDC_NAME,
205                  strlen(LUSTRE_MDC_NAME)))
206                 memcpy(qchk->obd_type, LUSTRE_MDS_NAME,
207                        strlen(LUSTRE_MDS_NAME));
208
209         RETURN(rc);
210 }
211
212 int lov_quota_check(struct obd_export *exp, struct obd_quotactl *oqctl)
213 {
214         struct obd_device *obd = class_exp2obd(exp);
215         struct lov_obd *lov = &obd->u.lov;
216         int i, rc = 0;
217         ENTRY;
218
219         for (i = 0; i < lov->desc.ld_tgt_count; i++) {
220                 int err;
221
222                 if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active) {
223                         CERROR("lov idx %d inactive\n", i);
224                         RETURN(-EIO);
225                 }
226
227                 err = obd_quotacheck(lov->lov_tgts[i]->ltd_exp, oqctl);
228                 if (err && lov->lov_tgts[i]->ltd_active && !rc)
229                         rc = err;
230         }
231
232         RETURN(rc);
233 }