Whamcloud - gitweb
LU-1146 build: batch update copyright messages
[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  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  *
32  * Copyright (c) 2011, 2012, Whamcloud, Inc.
33  */
34 /*
35  * This file is part of Lustre, http://www.lustre.org/
36  * Lustre is a trademark of Sun Microsystems, Inc.
37  */
38
39
40 #ifndef EXPORT_SYMTAB
41 # define EXPORT_SYMTAB
42 #endif
43 #define DEBUG_SUBSYSTEM S_LQUOTA
44
45 #ifdef __KERNEL__
46 # include <linux/version.h>
47 # include <linux/module.h>
48 # include <linux/init.h>
49 # include <linux/fs.h>
50 # include <linux/jbd.h>
51 # include <linux/ext3_fs.h>
52 # include <linux/smp_lock.h>
53 # include <linux/buffer_head.h>
54 # include <linux/workqueue.h>
55 # include <linux/mount.h>
56 #else /* __KERNEL__ */
57 # include <liblustre.h>
58 #endif
59
60 #include <obd_class.h>
61 #include <lustre_mds.h>
62 #include <lustre_dlm.h>
63 #include <lustre_cfg.h>
64 #include <obd_ost.h>
65 #include <lustre_fsfilt.h>
66 #include <lustre_quota.h>
67 #include "quota_internal.h"
68
69 #ifdef HAVE_QUOTA_SUPPORT
70 #ifdef __KERNEL__
71 static int target_quotacheck_callback(struct obd_export *exp,
72                                       struct obd_quotactl *oqctl)
73 {
74         struct ptlrpc_request *req;
75         struct obd_quotactl   *body;
76         int                    rc;
77         ENTRY;
78
79         req = ptlrpc_request_alloc_pack(exp->exp_imp_reverse, &RQF_QC_CALLBACK,
80                                         LUSTRE_OBD_VERSION, OBD_QC_CALLBACK);
81         if (req == NULL)
82                 RETURN(-ENOMEM);
83
84         body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
85         *body = *oqctl;
86
87         ptlrpc_request_set_replen(req);
88
89         rc = ptlrpc_queue_wait(req);
90         ptlrpc_req_finished(req);
91
92         RETURN(rc);
93 }
94
95 static int target_quotacheck_thread(void *data)
96 {
97         struct quotacheck_thread_args *qta = data;
98         struct obd_export *exp;
99         struct obd_device *obd;
100         struct obd_quotactl *oqctl;
101         struct lvfs_run_ctxt saved;
102         int rc;
103
104         cfs_daemonize_ctxt("quotacheck");
105
106         exp = qta->qta_exp;
107         obd = qta->qta_obd;
108         oqctl = &qta->qta_oqctl;
109
110         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
111
112         rc = fsfilt_quotacheck(obd, qta->qta_sb, oqctl);
113         if (rc)
114                 CERROR("%s: fsfilt_quotacheck: %d\n", obd->obd_name, rc);
115
116         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
117
118         rc = target_quotacheck_callback(exp, oqctl);
119         class_export_put(exp);
120         cfs_up(qta->qta_sem);
121         OBD_FREE_PTR(qta);
122         return rc;
123 }
124
125 int target_quota_check(struct obd_device *obd, struct obd_export *exp,
126                        struct obd_quotactl *oqctl)
127 {
128         struct obd_device_target *obt = &obd->u.obt;
129         struct quotacheck_thread_args *qta;
130         int rc = 0;
131         ENTRY;
132
133         OBD_ALLOC_PTR(qta);
134         if (!qta)
135                 RETURN(ENOMEM);
136
137         cfs_down(&obt->obt_quotachecking);
138
139         qta->qta_exp = exp;
140         qta->qta_obd = obd;
141         qta->qta_oqctl = *oqctl;
142         qta->qta_oqctl.qc_id = obt->obt_qfmt; /* override qfmt version */
143         qta->qta_sb = obt->obt_sb;
144         qta->qta_sem = &obt->obt_quotachecking;
145
146         /* quotaoff firstly */
147         oqctl->qc_cmd = Q_QUOTAOFF;
148         if (!strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME)) {
149                 rc = do_mds_quota_off(obd, oqctl);
150                 if (rc && rc != -EALREADY) {
151                         CERROR("off quota on MDS failed: %d\n", rc);
152                         GOTO(out, rc);
153                 }
154
155                 /* quota master */
156                 rc = init_admin_quotafiles(obd, &qta->qta_oqctl);
157                 if (rc) {
158                         CERROR("init_admin_quotafiles failed: %d\n", rc);
159                         GOTO(out, rc);
160                 }
161         } else {
162                 struct lvfs_run_ctxt saved;
163                 struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
164
165                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
166                 rc = fsfilt_quotactl(obd, obt->obt_sb, oqctl);
167                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
168                 if (!rc) {
169                         qctxt->lqc_flags &= ~UGQUOTA2LQC(oqctl->qc_type);
170                 } else if (!quota_is_off(qctxt, oqctl)) {
171                         CERROR("off quota on OSS failed: %d\n", rc);
172                         GOTO(out, rc);
173                 }
174         }
175
176         /* we get ref for exp because target_quotacheck_callback() will use this
177          * export later b=18126 */
178         class_export_get(exp);
179         rc = cfs_create_thread(target_quotacheck_thread, qta,
180                                CFS_DAEMON_FLAGS);
181         if (rc >= 0) {
182                 /* target_quotacheck_thread will drop the ref on exp and release
183                  * obt_quotachecking */
184                 CDEBUG(D_INFO, "%s: target_quotacheck_thread: %d\n",
185                        obd->obd_name, rc);
186                 RETURN(0);
187         } else {
188                 CERROR("%s: error starting quotacheck_thread: %d\n",
189                        obd->obd_name, rc);
190                 class_export_put(exp);
191                 EXIT;
192         }
193
194 out:
195         cfs_up(&obt->obt_quotachecking);
196         OBD_FREE_PTR(qta);
197         return rc;
198 }
199
200 #endif /* __KERNEL__ */
201 #endif /* HAVE_QUOTA_SUPPORT */