X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Finclude%2Flustre_quota.h;h=17ff2da6240cad6ece9ee171712b6ef74baec38b;hp=5e2e7afefa8b432c49ca6505768ce6263631b19f;hb=917655fc2938b90a9c246dd2d58408c42aa1658d;hpb=70e80ade90af09300396706b8910e196a7928520 diff --git a/lustre/include/lustre_quota.h b/lustre/include/lustre_quota.h index 5e2e7af..17ff2da 100644 --- a/lustre/include/lustre_quota.h +++ b/lustre/include/lustre_quota.h @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -16,422 +14,234 @@ * 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 [sun.com URL with a - * copy of GPLv2]. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * version 2 along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA * * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2012, 2017, Intel Corporation. * Use is subject to license terms. */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ #ifndef _LUSTRE_QUOTA_H #define _LUSTRE_QUOTA_H -#if defined(__linux__) -#include -#elif defined(__APPLE__) -#include -#elif defined(__WINNT__) -#include -#else -#error Unsupported operating system. -#endif - -#include -#include -#include +/** \defgroup quota quota + * + */ -struct obd_device; -struct client_obd; +#include +#include +#include +#include +#include +#include -#ifndef NR_DQHASH -#define NR_DQHASH 45 +#ifndef MAX_IQ_TIME +#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */ #endif -#ifdef HAVE_QUOTA_SUPPORT +#ifndef MAX_DQ_TIME +#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */ +#endif -#ifdef __KERNEL__ +struct lquota_id_info; +struct lquota_trans; -/* structures to access admin quotafile */ -struct lustre_mem_dqinfo { - unsigned int dqi_bgrace; - unsigned int dqi_igrace; - unsigned long dqi_flags; - unsigned int dqi_blocks; - unsigned int dqi_free_blk; - unsigned int dqi_free_entry; +/* Gather all quota record type in an union that can be used to read any records + * from disk. All fields of these records must be 64-bit aligned, otherwise the + * OSD layer may swab them incorrectly. */ +union lquota_rec { + struct lquota_glb_rec lqr_glb_rec; + struct lquota_slv_rec lqr_slv_rec; + struct lquota_acct_rec lqr_acct_rec; }; -struct lustre_quota_info { - struct file *qi_files[MAXQUOTAS]; - struct lustre_mem_dqinfo qi_info[MAXQUOTAS]; +/* flags for inode/block quota accounting */ +enum osd_qid_declare_flags { + OSD_QID_INODE = 1 << 0, + OSD_QID_BLK = 1 << 1, + OSD_QID_FORCE = 1 << 2, }; -#define DQ_STATUS_AVAIL 0x0 /* Available dquot */ -#define DQ_STATUS_SET 0x01 /* Sombody is setting dquot */ -#define DQ_STATUS_RECOVERY 0x02 /* dquot is in recovery */ - -struct lustre_dquot { - /* Hash list in memory, protect by dquot_hash_lock */ - struct list_head dq_hash; - /* Protect the data in lustre_dquot */ - struct semaphore dq_sem; - /* Use count */ - int dq_refcnt; - /* Pointer of quota info it belongs to */ - struct lustre_quota_info *dq_info; - - loff_t dq_off; /* Offset of dquot on disk */ - unsigned int dq_id; /* ID this applies to (uid, gid) */ - int dq_type; /* Type fo quota (USRQUOTA, GRPQUOUTA) */ - unsigned short dq_status; /* See DQ_STATUS_ */ - unsigned long dq_flags; /* See DQ_ in quota.h */ - struct mem_dqblk dq_dqb; /* Diskquota usage */ -}; +/* Index features supported by the global index objects + * Only used for migration purpose and should be removed once on-disk migration + * is no longer needed */ +extern struct dt_index_features dt_quota_iusr_features; +extern struct dt_index_features dt_quota_busr_features; +extern struct dt_index_features dt_quota_igrp_features; +extern struct dt_index_features dt_quota_bgrp_features; -struct dquot_id { - struct list_head di_link; - __u32 di_id; -}; +/* Name used in the configuration logs to identify the default metadata pool + * (composed of all the MDTs, with pool ID 0) and the default data pool (all + * the OSTs, with pool ID 0 too). */ +#define QUOTA_METAPOOL_NAME "mdt=" +#define QUOTA_DATAPOOL_NAME "ost=" -#define QFILE_CHK 1 -#define QFILE_RD_INFO 2 -#define QFILE_WR_INFO 3 -#define QFILE_INIT_INFO 4 -#define QFILE_RD_DQUOT 5 -#define QFILE_WR_DQUOT 6 - -/* admin quotafile operations */ -int lustre_check_quota_file(struct lustre_quota_info *lqi, int type); -int lustre_read_quota_info(struct lustre_quota_info *lqi, int type); -int lustre_write_quota_info(struct lustre_quota_info *lqi, int type); -int lustre_read_dquot(struct lustre_dquot *dquot); -int lustre_commit_dquot(struct lustre_dquot *dquot); -int lustre_init_quota_info(struct lustre_quota_info *lqi, int type); -int lustre_get_qids(struct file *file, struct inode *inode, int type, - struct list_head *list); - -#define LL_DQUOT_OFF(sb) DQUOT_OFF(sb) - -typedef int (*dqacq_handler_t) (struct obd_device * obd, struct qunit_data * qd, - int opc); -struct lustre_quota_ctxt { - struct super_block *lqc_sb; /* superblock this applies to */ - struct obd_import *lqc_import; /* import used to send dqacq/dqrel RPC */ - dqacq_handler_t lqc_handler; /* dqacq/dqrel RPC handler, only for quota master */ - unsigned long lqc_recovery:1, /* Doing recovery */ - lqc_atype:2, /* Turn on user/group quota at setup automatically, - * 0: none, 1: user quota, 2: group quota, 3: both */ - lqc_status:1; /* Quota status. 0:Off, 1:On */ - unsigned long lqc_iunit_sz; /* Unit size of file quota */ - unsigned long lqc_itune_sz; /* Trigger dqacq when available file quota less than - * this value, trigger dqrel when available file quota - * more than this value + 1 iunit */ - unsigned long lqc_bunit_sz; /* Unit size of block quota */ - unsigned long lqc_btune_sz; /* See comment of lqc_itune_sz */ -}; +/* + * Quota Master Target support + */ -#else +/* Request handlers for quota master operations. + * This is used by the MDT to pass quota/lock requests to the quota master + * target. This won't be needed any more once the QMT is a real target and + * does not rely any more on the MDT service threads and namespace. */ +struct qmt_handlers { + /* Handle quotactl request from client. */ + int (*qmth_quotactl)(const struct lu_env *, struct lu_device *, + struct obd_quotactl *); -struct lustre_quota_info { -}; + /* Handle dqacq/dqrel request from slave. */ + int (*qmth_dqacq)(const struct lu_env *, struct lu_device *, + struct ptlrpc_request *); -struct lustre_quota_ctxt { -}; + /* LDLM intent policy associated with quota locks */ + int (*qmth_intent_policy)(const struct lu_env *, struct lu_device *, + struct ptlrpc_request *, struct ldlm_lock **, + int); -#endif /* !__KERNEL__ */ + /* Initialize LVB of ldlm resource associated with quota objects */ + int (*qmth_lvbo_init)(struct lu_device *, struct ldlm_resource *); -#else + /* Update LVB of ldlm resource associated with quota objects */ + int (*qmth_lvbo_update)(struct lu_device *, struct ldlm_resource *, + struct ptlrpc_request *, int); -#define LL_DQUOT_OFF(sb) do {} while(0) + /* Return size of LVB to be packed in ldlm message */ + int (*qmth_lvbo_size)(struct lu_device *, struct ldlm_lock *); -struct lustre_quota_info { + /* Fill request buffer with lvb */ + int (*qmth_lvbo_fill)(struct lu_device *, struct ldlm_lock *, void *, + int); + + /* Free lvb associated with ldlm resource */ + int (*qmth_lvbo_free)(struct lu_device *, struct ldlm_resource *); }; -struct lustre_quota_ctxt { +/* actual handlers are defined in lustre/quota/qmt_handler.c */ +extern struct qmt_handlers qmt_hdls; + +/* + * Quota enforcement support on slaves + */ + +struct qsd_instance; + +/* The quota slave feature is implemented under the form of a library. + * The API is the following: + * + * - qsd_init(): the user (mostly the OSD layer) should first allocate a qsd + * instance via qsd_init(). This creates all required structures + * to manage quota enforcement for this target and performs all + * low-level initialization which does not involve any lustre + * object. qsd_init() should typically be called when the OSD + * is being set up. + * + * - qsd_prepare(): This sets up on-disk objects associated with the quota slave + * feature and initiates the quota reintegration procedure if + * needed. qsd_prepare() should typically be called when + * ->ldo_prepare is invoked. + * + * - qsd_start(): a qsd instance should be started once recovery is completed + * (i.e. when ->ldo_recovery_complete is called). This is used + * to notify the qsd layer that quota should now be enforced + * again via the qsd_op_begin/end functions. The last step of the + * reintegration prodecure (namely usage reconciliation) will be + * completed during start. + * + * - qsd_fini(): is used to release a qsd_instance structure allocated with + * qsd_init(). This releases all quota slave objects and frees the + * structures associated with the qsd_instance. + * + * - qsd_op_begin(): is used to enforce quota, it must be called in the + * declaration of each operation. qsd_op_end() should then be + * invoked later once all operations have been completed in + * order to release/adjust the quota space. + * Running qsd_op_begin() before qsd_start() isn't fatal and + * will return success. + * Once qsd_start() has been run, qsd_op_begin() will block + * until the reintegration procedure is completed. + * + * - qsd_op_end(): performs the post operation quota processing. This must be + * called after the operation transaction stopped. + * While qsd_op_begin() must be invoked each time a new + * operation is declared, qsd_op_end() should be called only + * once for the whole transaction. + * + * - qsd_op_adjust(): triggers pre-acquire/release if necessary. + * + * Below are the function prototypes to be used by OSD layer to manage quota + * enforcement. Arguments are documented where each function is defined. */ + +/* flags for quota local enforcement */ +enum osd_quota_local_flags { + QUOTA_FL_OVER_USRQUOTA = 1 << 0, + QUOTA_FL_OVER_GRPQUOTA = 1 << 1, + QUOTA_FL_SYNC = 1 << 2, + QUOTA_FL_OVER_PRJQUOTA = 1 << 3, }; -#endif /* !HAVE_QUOTA_SUPPORT */ +struct qsd_instance *qsd_init(const struct lu_env *, char *, struct dt_device *, + struct proc_dir_entry *, bool is_md); +int qsd_prepare(const struct lu_env *, struct qsd_instance *); +int qsd_start(const struct lu_env *, struct qsd_instance *); +void qsd_fini(const struct lu_env *, struct qsd_instance *); +int qsd_op_begin(const struct lu_env *, struct qsd_instance *, + struct lquota_trans *, struct lquota_id_info *, + enum osd_quota_local_flags *); +void qsd_op_end(const struct lu_env *, struct qsd_instance *, + struct lquota_trans *); +void qsd_op_adjust(const struct lu_env *, struct qsd_instance *, + union lquota_id *, int); -/* If the (quota limit < qunit * slave count), the slave which can't - * acquire qunit should set it's local limit as MIN_QLIMIT */ -#define MIN_QLIMIT 1 +/* + * Quota information attached to a transaction + */ -struct quotacheck_thread_args { - struct obd_export *qta_exp; /* obd export */ - struct obd_quotactl qta_oqctl; /* obd_quotactl args */ - struct super_block *qta_sb; /* obd super block */ - atomic_t *qta_sem; /* obt_quotachecking */ +struct lquota_entry; + +struct lquota_id_info { + /* quota identifier */ + union lquota_id lqi_id; + + /* USRQUOTA or GRPQUOTA for now, could be expanded for + * directory quota or other types later. */ + int lqi_type; + + /* inodes or kbytes to be consumed or released, it could + * be negative when releasing space. */ + long long lqi_space; + + /* quota slave entry structure associated with this ID */ + struct lquota_entry *lqi_qentry; + + /* whether we are reporting blocks or inodes */ + bool lqi_is_blk; }; -typedef struct { - int (*quota_init) (void); - int (*quota_exit) (void); - int (*quota_setup) (struct obd_device *); - int (*quota_cleanup) (struct obd_device *); - /* For quota master, close admin quota files */ - int (*quota_fs_cleanup) (struct obd_device *); - int (*quota_ctl) (struct obd_export *, struct obd_quotactl *); - int (*quota_check) (struct obd_export *, struct obd_quotactl *); - int (*quota_recovery) (struct obd_device *); - - /* For quota master/slave, adjust quota limit after fs operation */ - int (*quota_adjust) (struct obd_device *, unsigned int[], - unsigned int[], int, int); - - /* For quota slave, set import, trigger quota recovery */ - int (*quota_setinfo) (struct obd_export *, struct obd_device *); - - /* For quota slave, set proper thread resoure capability */ - int (*quota_enforce) (struct obd_device *, unsigned int); - - /* For quota slave, check whether specified uid/gid is over quota */ - int (*quota_getflag) (struct obd_device *, struct obdo *); - - /* For quota slave, acquire/release quota from master if needed */ - int (*quota_acquire) (struct obd_device *, unsigned int, unsigned int); - - /* For quota slave, check whether specified uid/gid's remaining quota - * can finish a write rpc */ - int (*quota_chkquota) (struct obd_device *, unsigned int, unsigned int, - int); - - /* For quota client, poll if the quota check done */ - int (*quota_poll_check) (struct obd_export *, struct if_quotacheck *); - - /* For quota client, check whether specified uid/gid is over quota */ - int (*quota_chkdq) (struct client_obd *, unsigned int, unsigned int); - - /* For quota client, set over quota flag for specifed uid/gid */ - int (*quota_setdq) (struct client_obd *, unsigned int, unsigned int, - obd_flag, obd_flag); -} quota_interface_t; - -#define Q_COPY(out, in, member) (out)->member = (in)->member - -#define QUOTA_OP(interface, op) interface->quota_ ## op - -#define QUOTA_CHECK_OP(interface, op) \ -do { \ - if (!interface) \ - RETURN(0); \ - if (!QUOTA_OP(interface, op)) { \ - CERROR("no quota operation: " #op "\n"); \ - RETURN(-EOPNOTSUPP); \ - } \ -} while(0) - -static inline int lquota_init(quota_interface_t *interface) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, init); - rc = QUOTA_OP(interface, init)(); - RETURN(rc); -} - -static inline int lquota_exit(quota_interface_t *interface) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, exit); - rc = QUOTA_OP(interface, exit)(); - RETURN(rc); -} - -static inline int lquota_setup(quota_interface_t *interface, - struct obd_device *obd) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, setup); - rc = QUOTA_OP(interface, setup)(obd); - RETURN(rc); -} - -static inline int lquota_cleanup(quota_interface_t *interface, - struct obd_device *obd) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, cleanup); - rc = QUOTA_OP(interface, cleanup)(obd); - RETURN(rc); -} - -static inline int lquota_fs_cleanup(quota_interface_t *interface, - struct obd_device *obd) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, fs_cleanup); - rc = QUOTA_OP(interface, fs_cleanup)(obd); - RETURN(rc); -} - -static inline int lquota_recovery(quota_interface_t *interface, - struct obd_device *obd) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, recovery); - rc = QUOTA_OP(interface, recovery)(obd); - RETURN(rc); -} - -static inline int lquota_adjust(quota_interface_t *interface, - struct obd_device *obd, - unsigned int qcids[], - unsigned int qpids[], - int rc, int opc) -{ - int ret; - ENTRY; - - QUOTA_CHECK_OP(interface, adjust); - ret = QUOTA_OP(interface, adjust)(obd, qcids, qpids, rc, opc); - RETURN(ret); -} - -static inline int lquota_chkdq(quota_interface_t *interface, - struct client_obd *cli, - unsigned int uid, unsigned int gid) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, chkdq); - rc = QUOTA_OP(interface, chkdq)(cli, uid, gid); - RETURN(rc); -} - -static inline int lquota_setdq(quota_interface_t *interface, - struct client_obd *cli, - unsigned int uid, unsigned int gid, - obd_flag valid, obd_flag flags) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, setdq); - rc = QUOTA_OP(interface, setdq)(cli, uid, gid, valid, flags); - RETURN(rc); -} - -static inline int lquota_poll_check(quota_interface_t *interface, - struct obd_export *exp, - struct if_quotacheck *qchk) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, poll_check); - rc = QUOTA_OP(interface, poll_check)(exp, qchk); - RETURN(rc); -} - - -static inline int lquota_setinfo(quota_interface_t *interface, - struct obd_export *exp, - struct obd_device *obd) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, setinfo); - rc = QUOTA_OP(interface, setinfo)(exp, obd); - RETURN(rc); -} - -static inline int lquota_enforce(quota_interface_t *interface, - struct obd_device *obd, - unsigned int ignore) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, enforce); - rc = QUOTA_OP(interface, enforce)(obd, ignore); - RETURN(rc); -} - -static inline int lquota_getflag(quota_interface_t *interface, - struct obd_device *obd, struct obdo *oa) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, getflag); - rc = QUOTA_OP(interface, getflag)(obd, oa); - RETURN(rc); -} - -static inline int lquota_acquire(quota_interface_t *interface, - struct obd_device *obd, - unsigned int uid, unsigned int gid) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, acquire); - rc = QUOTA_OP(interface, acquire)(obd, uid, gid); - RETURN(rc); -} - -static inline int lquota_chkquota(quota_interface_t *interface, - struct obd_device *obd, - unsigned int uid, unsigned int gid, - int npage) -{ - int rc; - ENTRY; - - QUOTA_CHECK_OP(interface, chkquota); - rc = QUOTA_OP(interface, chkquota)(obd, uid, gid, npage); - RETURN(rc); -} - -int lprocfs_rd_bunit(char *page, char **start, off_t off, int count, - int *eof, void *data); -int lprocfs_rd_iunit(char *page, char **start, off_t off, int count, - int *eof, void *data); -int lprocfs_wr_bunit(struct file *file, const char *buffer, - unsigned long count, void *data); -int lprocfs_wr_iunit(struct file *file, const char *buffer, - unsigned long count, void *data); -int lprocfs_rd_btune(char *page, char **start, off_t off, int count, - int *eof, void *data); -int lprocfs_rd_itune(char *page, char **start, off_t off, int count, - int *eof, void *data); -int lprocfs_wr_btune(struct file *file, const char *buffer, - unsigned long count, void *data); -int lprocfs_wr_itune(struct file *file, const char *buffer, - unsigned long count, void *data); -int lprocfs_rd_type(char *page, char **start, off_t off, int count, - int *eof, void *data); -int lprocfs_wr_type(struct file *file, const char *buffer, - unsigned long count, void *data); - -#ifndef __KERNEL__ -extern quota_interface_t osc_quota_interface; -extern quota_interface_t mdc_quota_interface; -extern quota_interface_t lov_quota_interface; -#endif +/* With the DoM, both inode quota in meta pool and block quota in data pool + * will be enforced at MDT, there are at most 4 quota ids being enforced in + * a single transaction for inode and block quota, which is chown transaction: + * original uid and gid, new uid and gid. + * + * This value might need to be revised when directory quota is added. */ +#define QUOTA_MAX_TRANSIDS 8 + +/* all qids involved in a single transaction */ +struct lquota_trans { + unsigned short lqt_id_cnt; + struct lquota_id_info lqt_ids[QUOTA_MAX_TRANSIDS]; +}; + +#define IS_LQUOTA_RES(res) \ + (res->lr_name.name[LUSTRE_RES_ID_SEQ_OFF] == FID_SEQ_QUOTA || \ + res->lr_name.name[LUSTRE_RES_ID_SEQ_OFF] == FID_SEQ_QUOTA_GLB) +/* helper function used by MDT & OFD to retrieve quota accounting information + * on slave */ +int lquotactl_slv(const struct lu_env *, struct dt_device *, + struct obd_quotactl *); +/** @} quota */ #endif /* _LUSTRE_QUOTA_H */