@@ -38,6 +38,7 @@
#include <linux/percpu_counter.h>
#include <linux/libcfs/libcfs.h>
#include <linux/ctype.h>
+#include <obd_target.h>
#include <uapi/linux/lustre/lustre_idl.h>
#include <lu_ref.h>
@@ -1399,16 +1400,6 @@ struct lu_kmem_descr {
extern u32 lu_context_tags_default;
extern u32 lu_session_tags_default;
-/* Generic subset of tgts */
-struct lu_tgt_pool {
- u32 *op_array; /* array of index of
- * lov_obd->lov_tgts
- */
- unsigned int op_count; /* number of tgts in the array */
- unsigned int op_size; /* allocated size of op_array */
- struct rw_semaphore op_rw_sem; /* to protect lu_tgt_pool use */
-};
-
/* round-robin QoS data for LOD/LMV */
struct lu_qos_rr {
spinlock_t lqr_alloc; /* protect allocation index */
@@ -266,6 +266,7 @@ void req_capsule_shrink(struct req_capsule *pill,
extern struct req_msg_field RMF_CAPA2;
extern struct req_msg_field RMF_OBD_QUOTACHECK;
extern struct req_msg_field RMF_OBD_QUOTACTL;
+extern struct req_msg_field RMF_OBD_QUOTACTL_POOL;
extern struct req_msg_field RMF_STRING;
extern struct req_msg_field RMF_SWAP_LAYOUTS;
extern struct req_msg_field RMF_MDS_HSM_PROGRESS;
@@ -60,7 +60,7 @@
void lustre_swab_niobuf_remote(struct niobuf_remote *nbr);
void lustre_swab_ost_lvb_v1(struct ost_lvb_v1 *lvb);
void lustre_swab_ost_lvb(struct ost_lvb *lvb);
-void lustre_swab_obd_quotactl(struct obd_quotactl *q);
+int lustre_swab_obd_quotactl(struct obd_quotactl *q, u32 len);
void lustre_swab_lquota_lvb(struct lquota_lvb *lvb);
void lustre_swab_generic_32s(u32 *val);
void lustre_swab_mdt_body(struct mdt_body *b);
new file mode 100644
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+/* GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright (c) 2011, 2014, Intel Corporation.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ */
+
+#ifndef __OBD_TARGET_H
+#define __OBD_TARGET_H
+#include <lprocfs_status.h>
+
+/* Generic subset of tgts */
+struct lu_tgt_pool {
+ __u32 *op_array; /* array of index of
+ * lov_obd->lov_tgts
+ */
+ unsigned int op_count; /* number of tgts in the array */
+ unsigned int op_size; /* allocated size of op_array */
+ struct rw_semaphore op_rw_sem; /* to protect lu_tgt_pool use */
+};
+
+int tgt_pool_init(struct lu_tgt_pool *op, unsigned int count);
+int tgt_pool_add(struct lu_tgt_pool *op, __u32 idx, unsigned int min_count);
+int tgt_pool_remove(struct lu_tgt_pool *op, __u32 idx);
+int tgt_pool_free(struct lu_tgt_pool *op);
+int tgt_check_index(int idx, struct lu_tgt_pool *osts);
+int tgt_pool_extend(struct lu_tgt_pool *op, unsigned int min_count);
+
+#endif /* __OBD_TARGET_H */
@@ -1083,15 +1083,19 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
case Q_SETQUOTA:
case Q_SETINFO:
case LUSTRE_Q_SETDEFAULT:
+ case LUSTRE_Q_SETQUOTAPOOL:
+ case LUSTRE_Q_SETINFOPOOL:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
break;
case Q_GETQUOTA:
case LUSTRE_Q_GETDEFAULT:
+ case LUSTRE_Q_GETQUOTAPOOL:
if (check_owner(type, id) && !capable(CAP_SYS_ADMIN))
return -EPERM;
break;
case Q_GETINFO:
+ case LUSTRE_Q_GETINFOPOOL:
break;
default:
CERROR("unsupported quotactl op: %#x\n", cmd);
@@ -1101,7 +1105,8 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
if (valid != QC_GENERAL) {
if (cmd == Q_GETINFO)
qctl->qc_cmd = Q_GETOINFO;
- else if (cmd == Q_GETQUOTA)
+ else if (cmd == Q_GETQUOTA ||
+ cmd == LUSTRE_Q_GETQUOTAPOOL)
qctl->qc_cmd = Q_GETOQUOTA;
else
return -EINVAL;
@@ -1134,8 +1139,12 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
qctl->qc_cmd = cmd;
} else {
struct obd_quotactl *oqctl;
+ int oqctl_len = sizeof(*oqctl);
- oqctl = kzalloc(sizeof(*oqctl), GFP_NOFS);
+ if (LUSTRE_Q_CMD_IS_POOL(cmd))
+ oqctl_len += LOV_MAXPOOLNAME + 1;
+
+ oqctl = kzalloc(oqctl_len, GFP_NOFS);
if (!oqctl)
return -ENOMEM;
@@ -1148,7 +1157,7 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
/* If QIF_SPACE is not set, client should collect the
* space usage from OSSs by itself
*/
- if (cmd == Q_GETQUOTA &&
+ if ((cmd == Q_GETQUOTA || cmd == LUSTRE_Q_GETQUOTAPOOL) &&
!(oqctl->qc_dqblk.dqb_valid & QIF_SPACE) &&
!oqctl->qc_dqblk.dqb_curspace) {
struct obd_quotactl *oqctl_tmp;
@@ -1807,8 +1816,9 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
case OBD_IOC_QUOTACTL: {
struct if_quotactl *qctl;
+ int qctl_len = sizeof(*qctl) + LOV_MAXPOOLNAME + 1;
- qctl = kzalloc(sizeof(*qctl), GFP_NOFS);
+ qctl = kzalloc(qctl_len, GFP_NOFS);
if (!qctl)
return -ENOMEM;
@@ -1817,8 +1827,18 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto out_quotactl;
}
- rc = quotactl_ioctl(sbi, qctl);
+ if (LUSTRE_Q_CMD_IS_POOL(qctl->qc_cmd)) {
+ char __user *from = (char __user *)arg +
+ offsetof(typeof(*qctl), qc_poolname);
+ if (copy_from_user(qctl->qc_poolname, from,
+ LOV_MAXPOOLNAME + 1)) {
+ rc = -EFAULT;
+ goto out_quotactl;
+ }
+ }
+
+ rc = quotactl_ioctl(sbi, qctl);
if (rc == 0 && copy_to_user((void __user *)arg, qctl,
sizeof(*qctl)))
rc = -EFAULT;
@@ -2073,34 +2073,50 @@ static int mdc_quotactl(struct obd_device *unused, struct obd_export *exp,
struct obd_quotactl *oqc;
int rc;
- req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
- &RQF_MDS_QUOTACTL, LUSTRE_MDS_VERSION,
- MDS_QUOTACTL);
+ req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_QUOTACTL);
if (!req)
return -ENOMEM;
+ if (LUSTRE_Q_CMD_IS_POOL(oqctl->qc_cmd))
+ req_capsule_set_size(&req->rq_pill,
+ &RMF_OBD_QUOTACTL,
+ RCL_CLIENT,
+ sizeof(*oqc) + LOV_MAXPOOLNAME + 1);
+
+ rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION,
+ MDS_QUOTACTL);
+ if (rc) {
+ ptlrpc_request_free(req);
+ return rc;
+ }
+
oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
- *oqc = *oqctl;
+ QCTL_COPY(oqc, oqctl);
ptlrpc_request_set_replen(req);
ptlrpc_at_set_req_timeout(req);
rc = ptlrpc_queue_wait(req);
- if (rc)
- CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
+ if (rc) {
+ CERROR("%s: ptlrpc_queue_wait failed: rc = %d\n",
+ exp->exp_obd->obd_name, rc);
+ goto out;
+ }
if (req->rq_repmsg) {
oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
if (oqc) {
- *oqctl = *oqc;
- } else if (!rc) {
- CERROR("Can't unpack obd_quotactl\n");
- rc = -EPROTO;
+ QCTL_COPY(oqctl, oqc);
+ goto out;
}
- } else if (!rc) {
- CERROR("Can't unpack obd_quotactl\n");
+ }
+
+ if (!rc) {
rc = -EPROTO;
+ CERROR("%s: cannot unpack obd_quotactl: rc = %d\n",
+ exp->exp_obd->obd_name, rc);
}
+out:
ptlrpc_req_finished(req);
return rc;
@@ -923,9 +923,9 @@ struct req_msg_field RMF_MDT_BODY =
EXPORT_SYMBOL(RMF_MDT_BODY);
struct req_msg_field RMF_OBD_QUOTACTL =
- DEFINE_MSGF("obd_quotactl", 0,
- sizeof(struct obd_quotactl),
- lustre_swab_obd_quotactl, NULL);
+ DEFINE_MSGFL("obd_quotactl", 0,
+ sizeof(struct obd_quotactl),
+ lustre_swab_obd_quotactl, NULL);
EXPORT_SYMBOL(RMF_OBD_QUOTACTL);
struct req_msg_field RMF_MDT_EPOCH =
@@ -1893,14 +1893,19 @@ static void lustre_swab_obd_dqblk(struct obd_dqblk *b)
BUILD_BUG_ON(offsetof(typeof(*b), dqb_padding) == 0);
}
-void lustre_swab_obd_quotactl(struct obd_quotactl *q)
+int lustre_swab_obd_quotactl(struct obd_quotactl *q, u32 len)
{
+ if (unlikely(len <= sizeof(struct obd_quotactl)))
+ return -EOVERFLOW;
+
__swab32s(&q->qc_cmd);
__swab32s(&q->qc_type);
__swab32s(&q->qc_id);
__swab32s(&q->qc_stat);
lustre_swab_obd_dqinfo(&q->qc_dqinfo);
lustre_swab_obd_dqblk(&q->qc_dqblk);
+
+ return len;
}
void lustre_swab_fid2path(struct getinfo_fid2path *gf)
@@ -1363,18 +1363,23 @@ struct obd_quotactl {
__u32 qc_stat;
struct obd_dqinfo qc_dqinfo;
struct obd_dqblk qc_dqblk;
+ char qc_poolname[0];
};
#define Q_COPY(out, in, member) (out)->member = (in)->member
-#define QCTL_COPY(out, in) \
-do { \
- Q_COPY(out, in, qc_cmd); \
- Q_COPY(out, in, qc_type); \
- Q_COPY(out, in, qc_id); \
- Q_COPY(out, in, qc_stat); \
- Q_COPY(out, in, qc_dqinfo); \
- Q_COPY(out, in, qc_dqblk); \
+#define QCTL_COPY(out, in) \
+do { \
+ Q_COPY(out, in, qc_cmd); \
+ Q_COPY(out, in, qc_type); \
+ Q_COPY(out, in, qc_id); \
+ Q_COPY(out, in, qc_stat); \
+ Q_COPY(out, in, qc_dqinfo); \
+ Q_COPY(out, in, qc_dqblk); \
+ if (LUSTRE_Q_CMD_IS_POOL(in->qc_cmd)) \
+ memcpy(out->qc_poolname, \
+ in->qc_poolname, \
+ LOV_MAXPOOLNAME + 1); \
} while (0)
/* Data structures associated with the quota locks */
@@ -890,6 +890,10 @@ static inline void obd_uuid2fsname(char *buf, char *uuid, int buflen)
#define LUSTRE_Q_FINVALIDATE 0x80000c /* deprecated as of 2.4 */
#define LUSTRE_Q_GETDEFAULT 0x80000d /* get default quota */
#define LUSTRE_Q_SETDEFAULT 0x80000e /* set default quota */
+#define LUSTRE_Q_GETQUOTAPOOL 0x80000f /* get user pool quota */
+#define LUSTRE_Q_SETQUOTAPOOL 0x800010 /* set user pool quota */
+#define LUSTRE_Q_GETINFOPOOL 0x800011 /* get pool quota info */
+#define LUSTRE_Q_SETINFOPOOL 0x800012 /* set pool quota info */
/* In the current Lustre implementation, the grace time is either the time
* or the timestamp to be used after some quota ID exceeds the soft limt,
@@ -911,6 +915,12 @@ static inline void obd_uuid2fsname(char *buf, char *uuid, int buflen)
*/
#define LQUOTA_FLAG_DEFAULT 0x0001
+#define LUSTRE_Q_CMD_IS_POOL(cmd) \
+ (cmd == LUSTRE_Q_GETQUOTAPOOL || \
+ cmd == LUSTRE_Q_SETQUOTAPOOL || \
+ cmd == LUSTRE_Q_SETINFOPOOL || \
+ cmd == LUSTRE_Q_GETINFOPOOL)
+
#define ALLQUOTA 255 /* set all quota */
static inline const char *qtype_name(int qtype)
@@ -1009,6 +1019,7 @@ struct if_quotactl {
struct obd_dqblk qc_dqblk;
char obd_type[16];
struct obd_uuid obd_uuid;
+ char qc_poolname[0];
};
/* swap layout flags */