Whamcloud - gitweb
dfffb8681c2bf72f37538e63146432f1e4148cca
[fs/lustre-release.git] / lustre / quota / lquota_lib.c
1 /*
2  *
3  * GPL HEADER START
4  *
5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 only,
9  * as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License version 2 for more details (a copy is included
15  * in the LICENSE file that accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License
18  * version 2 along with this program; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 021110-1307, USA
21  *
22  * GPL HEADER END
23  */
24 /*
25  * Copyright (c) 2011, 2012, Whamcloud, Inc.
26  * Use is subject to license terms.
27  *
28  * Author: Johann Lombardi <johann@whamcloud.com>
29  * Author: Niu    Yawei    <niu@whamcloud.com>
30  */
31
32 #ifndef EXPORT_SYMTAB
33 # define EXPORT_SYMTAB
34 #endif
35
36 #define DEBUG_SUBSYSTEM S_LQUOTA
37
38 #include "lquota_internal.h"
39
40 static struct dt_object_format dt_acct_format = {
41         .dof_type               = DFT_INDEX,
42         .u.dof_idx.di_feat      = &dt_acct_features
43 };
44
45 /**
46  * Look-up accounting object to collect space usage information for user
47  * or group.
48  *
49  * \param env - is the environment passed by the caller
50  * \param dev - is the dt_device storing the accounting object
51  * \param oid - is the object id of the accounting object to initialize, must be
52  *              either ACCT_USER_OID or ACCT_GROUP_OID.
53  */
54 struct dt_object *acct_obj_lookup(const struct lu_env *env,
55                                   struct dt_device *dev, __u32 oid)
56 {
57         struct dt_object        *obj = NULL;
58         struct lu_fid            fid;
59         struct lu_attr           attr;
60         int                      rc;
61         ENTRY;
62
63         memset(&attr, 0, sizeof(attr));
64         attr.la_valid = LA_MODE;
65         attr.la_mode = S_IFREG | S_IRUGO | S_IWUSR;
66         lu_local_obj_fid(&fid, oid);
67
68         /* lookup/create the accounting object */
69         obj = dt_find_or_create(env, dev, &fid, &dt_acct_format, &attr);
70         if (IS_ERR(obj))
71                 RETURN(obj);
72
73         if (obj->do_index_ops == NULL) {
74                 /* set up indexing operations */
75                 rc = obj->do_ops->do_index_try(env, obj, &dt_acct_features);
76                 if (rc) {
77                         lu_object_put(env, &obj->do_lu);
78                         RETURN(ERR_PTR(rc));
79                 }
80         }
81         RETURN(obj);
82 }
83
84 /*
85  * Helper routine to retrieve slave information.
86  * This function converts a quotactl request into quota/accounting object
87  * operations. It is independant of the slave stack which is only accessible
88  * from the OSD layer.
89  *
90  * \param env   - is the environment passed by the caller
91  * \param dev   - is the dt_device this quotactl is executed on
92  * \param oqctl - is the quotactl request
93  */
94 int lquotactl_slv(const struct lu_env *env, struct dt_device *dev,
95                   struct obd_quotactl *oqctl)
96 {
97         struct acct_rec          rec;
98         __u64                    key;
99         struct dt_object        *obj;
100         int                      rc = 0;
101         ENTRY;
102
103         if (oqctl->qc_cmd != Q_GETOQUOTA) {
104                 /* as in many other places, dev->dd_lu_dev.ld_obd->obd_name
105                  * point to a valid obd_name, to be fixed in LU-1574 */
106                 CERROR("%s: Unsupported quotactl command: %x\n",
107                        dev->dd_lu_dev.ld_obd->obd_name, oqctl->qc_cmd);
108                 RETURN(-EOPNOTSUPP);
109         }
110
111         if (oqctl->qc_type == USRQUOTA)
112                 obj = acct_obj_lookup(env, dev, ACCT_USER_OID);
113         else if (oqctl->qc_type == GRPQUOTA)
114                 obj = acct_obj_lookup(env, dev, ACCT_GROUP_OID);
115         else
116                 /* no support for directory quota yet */
117                 RETURN(-EOPNOTSUPP);
118
119         if (IS_ERR(obj))
120                 RETURN(-EOPNOTSUPP);
121         if (obj->do_index_ops == NULL)
122                 GOTO(out, rc = -EINVAL);
123
124         /* qc_id is a 32-bit field while a key has 64 bits */
125         key = oqctl->qc_id;
126
127         /* lookup record storing space accounting information for this ID */
128         rc = dt_lookup(env, obj, (struct dt_rec *)&rec, (struct dt_key *)&key,
129                        BYPASS_CAPA);
130         if (rc < 0)
131                 GOTO(out, rc);
132
133         memset(&oqctl->qc_dqblk, 0, sizeof(struct obd_dqblk));
134         oqctl->qc_dqblk.dqb_curspace  = rec.bspace;
135         oqctl->qc_dqblk.dqb_curinodes = rec.ispace;
136         oqctl->qc_dqblk.dqb_valid     = QIF_USAGE;
137         /* TODO: must set {hard,soft}limit and grace time */
138
139         EXIT;
140 out:
141         lu_object_put(env, &obj->do_lu);
142         return rc;
143 }
144 EXPORT_SYMBOL(lquotactl_slv);