Whamcloud - gitweb
LU-1182 ldiskfs-osd: space accounting support
[fs/lustre-release.git] / lustre / quota / lquota_lib.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) 2011, 2012, Whamcloud, Inc.
25  * Use is subject to license terms.
26  *
27  * Author: Johann Lombardi <johann@whamcloud.com>
28  * Author: Niu    Yawei    <niu@whamcloud.com>
29  */
30
31 #ifndef EXPORT_SYMTAB
32 # define EXPORT_SYMTAB
33 #endif
34
35 #define DEBUG_SUBSYSTEM S_LQUOTA
36
37 #include "lquota_internal.h"
38
39 static struct dt_object_format dt_acct_format = {
40         .dof_type               = DFT_INDEX,
41         .u.dof_idx.di_feat      = &dt_acct_features
42 };
43
44 /**
45  * Look-up accounting object to collect space usage information for user
46  * or group.
47  *
48  * \param env - is the environment passed by the caller
49  * \param dev - is the dt_device storing the accounting object
50  * \param oid - is the object id of the accounting object to initialize, must be
51  *              either ACCT_USER_OID or ACCT_GROUP_OID.
52  */
53 struct dt_object *acct_obj_lookup(const struct lu_env *env,
54                                   struct dt_device *dev, __u32 oid)
55 {
56         struct dt_object        *obj = NULL;
57         struct lu_fid            fid;
58         struct lu_attr           attr;
59         int                      rc;
60         ENTRY;
61
62         memset(&attr, 0, sizeof(attr));
63         attr.la_valid = LA_MODE;
64         attr.la_mode = S_IFREG | S_IRUGO | S_IWUSR;
65         lu_local_obj_fid(&fid, oid);
66
67         /* lookup/create the accounting object */
68         obj = dt_find_or_create(env, dev, &fid, &dt_acct_format, &attr);
69         if (IS_ERR(obj))
70                 RETURN(obj);
71
72         if (obj->do_index_ops == NULL) {
73                 /* set up indexing operations */
74                 rc = obj->do_ops->do_index_try(env, obj, &dt_acct_features);
75                 if (rc) {
76                         lu_object_put(env, &obj->do_lu);
77                         RETURN(ERR_PTR(rc));
78                 }
79         }
80         RETURN(obj);
81 }
82
83 /*
84  * Helper routine to retrieve slave information.
85  * This function converts a quotactl request into quota/accounting object
86  * operations. It is independant of the slave stack which is only accessible
87  * from the OSD layer.
88  *
89  * \param env   - is the environment passed by the caller
90  * \param dev   - is the dt_device this quotactl is executed on
91  * \param oqctl - is the quotactl request
92  */
93 int lquotactl_slv(const struct lu_env *env, struct dt_device *dev,
94                   struct obd_quotactl *oqctl)
95 {
96         struct acct_rec          rec;
97         __u64                    key;
98         struct dt_object        *obj;
99         int                      rc = 0;
100         ENTRY;
101
102         if (oqctl->qc_cmd != Q_GETOQUOTA) {
103                 /* as in many other places, dev->dd_lu_dev.ld_obd->obd_name
104                  * point to a valid obd_name, to be fixed in LU-1574 */
105                 CERROR("%s: Unsupported quotactl command: %x\n",
106                        dev->dd_lu_dev.ld_obd->obd_name, oqctl->qc_cmd);
107                 RETURN(-EOPNOTSUPP);
108         }
109
110         if (oqctl->qc_type == USRQUOTA)
111                 obj = acct_obj_lookup(env, dev, ACCT_USER_OID);
112         else if (oqctl->qc_type == GRPQUOTA)
113                 obj = acct_obj_lookup(env, dev, ACCT_GROUP_OID);
114         else
115                 /* no support for directory quota yet */
116                 RETURN(-EOPNOTSUPP);
117
118         if (IS_ERR(obj))
119                 RETURN(-EOPNOTSUPP);
120         if (obj->do_index_ops == NULL)
121                 GOTO(out, rc = -EINVAL);
122
123         /* qc_id is a 32-bit field while a key has 64 bits */
124         key = oqctl->qc_id;
125
126         /* lookup record storing space accounting information for this ID */
127         rc = dt_lookup(env, obj, (struct dt_rec *)&rec, (struct dt_key *)&key,
128                        BYPASS_CAPA);
129         if (rc < 0)
130                 GOTO(out, rc);
131
132         memset(&oqctl->qc_dqblk, 0, sizeof(struct obd_dqblk));
133         oqctl->qc_dqblk.dqb_curspace  = rec.bspace;
134         oqctl->qc_dqblk.dqb_curinodes = rec.ispace;
135         oqctl->qc_dqblk.dqb_valid     = QIF_USAGE;
136         /* TODO: must set {hard,soft}limit and grace time */
137
138         EXIT;
139 out:
140         lu_object_put(env, &obj->do_lu);
141         return rc;
142 }
143 EXPORT_SYMBOL(lquotactl_slv);