LU_KEY_INIT_GENERIC(qsd);
/* some procfs helpers */
-static int lprocfs_qsd_rd_state(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int qsd_state_seq_show(struct seq_file *m, void *data)
{
- struct qsd_instance *qsd = (struct qsd_instance *)data;
+ struct qsd_instance *qsd = m->private;
char enabled[5];
int rc;
if (strlen(enabled) == 0)
strcat(enabled, "none");
- rc = snprintf(page, count,
- "target name: %s\n"
- "pool ID: %d\n"
- "type: %s\n"
- "quota enabled: %s\n"
- "conn to master: %s\n",
- qsd->qsd_svname, qsd->qsd_pool_id,
- qsd->qsd_is_md ? "md" : "dt", enabled,
- qsd->qsd_exp_valid ? "setup" : "not setup yet");
+ rc = seq_printf(m, "target name: %s\n"
+ "pool ID: %d\n"
+ "type: %s\n"
+ "quota enabled: %s\n"
+ "conn to master: %s\n",
+ qsd->qsd_svname, qsd->qsd_pool_id,
+ qsd->qsd_is_md ? "md" : "dt", enabled,
+ qsd->qsd_exp_valid ? "setup" : "not setup yet");
if (qsd->qsd_prepared) {
memset(enabled, 0, sizeof(enabled));
strcat(enabled, "g");
if (strlen(enabled) == 0)
strcat(enabled, "none");
- rc += snprintf(page + rc, count - rc,
- "space acct: %s\n"
+ rc += seq_printf(m, "space acct: %s\n"
"user uptodate: glb[%d],slv[%d],reint[%d]\n"
"group uptodate: glb[%d],slv[%d],reint[%d]\n",
enabled,
}
return rc;
}
+LPROC_SEQ_FOPS_RO(qsd_state);
-static int lprocfs_qsd_rd_enabled(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int qsd_enabled_seq_show(struct seq_file *m, void *data)
{
- struct qsd_instance *qsd = (struct qsd_instance *)data;
+ struct qsd_instance *qsd = m->private;
char enabled[5];
LASSERT(qsd != NULL);
if (strlen(enabled) == 0)
strcat(enabled, "none");
- return snprintf(page, count, "%s\n", enabled);
+ return seq_printf(m, "%s\n", enabled);
}
+LPROC_SEQ_FOPS_RO(qsd_enabled);
/* force reintegration procedure to be executed.
* Used for test/debugging purpose */
-static int lprocfs_qsd_wr_force_reint(struct file *file, const char *buffer,
- unsigned long count, void *data)
+static ssize_t
+lprocfs_force_reint_seq_write(struct file *file, const char *buffer,
+ size_t count, loff_t *off)
{
- struct qsd_instance *qsd = (struct qsd_instance *)data;
- int rc = 0, qtype;
+ struct qsd_instance *qsd = ((struct seq_file *)file->private_data)->private;
+ int rc = 0, qtype;
LASSERT(qsd != NULL);
}
return rc == 0 ? count : rc;
}
+LPROC_SEQ_FOPS_WO_TYPE(qsd, force_reint);
-static int lprocfs_qsd_rd_timeout(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int qsd_timeout_seq_show(struct seq_file *m, void *data)
{
- struct qsd_instance *qsd = (struct qsd_instance *)data;
+ struct qsd_instance *qsd = m->private;
LASSERT(qsd != NULL);
- return snprintf(page, count, "%d\n", qsd_wait_timeout(qsd));
+ return seq_printf(m, "%d\n", qsd_wait_timeout(qsd));
}
-static int lprocfs_qsd_wr_timeout(struct file *file, const char *buffer,
- unsigned long count, void *data)
+static ssize_t
+qsd_timeout_seq_write(struct file *file, const char *buffer,
+ size_t count, loff_t *off)
{
- struct qsd_instance *qsd = (struct qsd_instance *)data;
- int timeout, rc;
+ struct qsd_instance *qsd = ((struct seq_file *)file->private_data)->private;
+ int timeout, rc;
LASSERT(qsd != NULL);
rc = lprocfs_write_helper(buffer, count, &timeout);
qsd->qsd_timeout = timeout;
return count;
}
+LPROC_SEQ_FOPS(qsd_timeout);
-static struct lprocfs_vars lprocfs_quota_qsd_vars[] = {
- { "info", lprocfs_qsd_rd_state, 0, 0},
- { "enabled", lprocfs_qsd_rd_enabled, 0, 0},
- { "force_reint", 0, lprocfs_qsd_wr_force_reint, 0},
- { "timeout", lprocfs_qsd_rd_timeout, lprocfs_qsd_wr_timeout, 0},
+static struct lprocfs_seq_vars lprocfs_quota_qsd_vars[] = {
+ { "info", &qsd_state_fops },
+ { "enabled", &qsd_enabled_fops },
+ { "force_reint", &qsd_force_reint_fops },
+ { "timeout", &qsd_timeout_fops },
{ NULL }
};
* step 3) will have to wait for qsd_start() to be called */
for (type = USRQUOTA; type < MAXQUOTAS; type++) {
struct qsd_qtype_info *qqi = qsd->qsd_type_array[type];
- cfs_waitq_signal(&qqi->qqi_reint_thread.t_ctl_waitq);
+ wake_up(&qqi->qqi_reint_thread.t_ctl_waitq);
}
RETURN(0);
int qtype)
{
struct qsd_qtype_info *qqi;
+ int repeat = 0;
ENTRY;
if (qsd->qsd_type_array[qtype] == NULL)
qqi->qqi_site = NULL;
}
+ /* The qqi may still be holding by global locks which are being
+ * canceled asynchronously (LU-4365), see the following steps:
+ *
+ * - On server umount, we try to clear all quota locks first by
+ * disconnecting LWP (which will invalidate import and cleanup
+ * all locks on it), however, if quota reint process is holding
+ * the global lock for reintegration at that time, global lock
+ * will fail to be cleared on LWP disconnection.
+ *
+ * - Umount process goes on and stops reint process, the global
+ * lock will be dropped on reint process exit, however, the lock
+ * cancel in done in asynchronous way, so the
+ * qsd_glb_blocking_ast() might haven't been called yet when we
+ * get here.
+ */
+ while (cfs_atomic_read(&qqi->qqi_ref) > 1) {
+ CDEBUG(D_QUOTA, "qqi reference count %u, repeat: %d\n",
+ cfs_atomic_read(&qqi->qqi_ref), repeat);
+ repeat++;
+ schedule_timeout_and_set_state(TASK_INTERRUPTIBLE,
+ cfs_time_seconds(1));
+ }
+
/* by now, all qqi users should have gone away */
LASSERT(cfs_atomic_read(&qqi->qqi_ref) == 1);
lu_ref_fini(&qqi->qqi_reference);
qqi->qqi_glb_uptodate = false;
qqi->qqi_slv_uptodate = false;
qqi->qqi_reint = false;
- cfs_waitq_init(&qqi->qqi_reint_thread.t_ctl_waitq);
+ init_waitqueue_head(&qqi->qqi_reint_thread.t_ctl_waitq);
thread_set_flags(&qqi->qqi_reint_thread, SVC_STOPPED);
CFS_INIT_LIST_HEAD(&qqi->qqi_deferred_glb);
CFS_INIT_LIST_HEAD(&qqi->qqi_deferred_slv);
/* only configure qsd for MDT & OST */
type = server_name2index(svname, &idx, NULL);
if (type != LDD_F_SV_TYPE_MDT && type != LDD_F_SV_TYPE_OST)
- RETURN(ERR_PTR(-EINVAL));
+ RETURN(NULL);
/* allocate qsd instance */
OBD_ALLOC_PTR(qsd);
rwlock_init(&qsd->qsd_lock);
CFS_INIT_LIST_HEAD(&qsd->qsd_link);
thread_set_flags(&qsd->qsd_upd_thread, SVC_STOPPED);
- cfs_waitq_init(&qsd->qsd_upd_thread.t_ctl_waitq);
+ init_waitqueue_head(&qsd->qsd_upd_thread.t_ctl_waitq);
CFS_INIT_LIST_HEAD(&qsd->qsd_upd_list);
spin_lock_init(&qsd->qsd_adjust_lock);
CFS_INIT_LIST_HEAD(&qsd->qsd_adjust_list);
up(&qsd->qsd_fsinfo->qfs_sem);
/* register procfs directory */
- qsd->qsd_proc = lprocfs_register(QSD_DIR, osd_proc,
- lprocfs_quota_qsd_vars, qsd);
+ qsd->qsd_proc = lprocfs_seq_register(QSD_DIR, osd_proc,
+ lprocfs_quota_qsd_vars, qsd);
if (IS_ERR(qsd->qsd_proc)) {
rc = PTR_ERR(qsd->qsd_proc);
qsd->qsd_proc = NULL;
}
/* generate osp name */
- rc = tgt_name2lwpname((char *)qsd->qsd_svname, qti->qti_buf);
+ rc = tgt_name2lwp_name(qsd->qsd_svname, qti->qti_buf,
+ MTI_NAME_MAXLEN, 0);
if (rc) {
CERROR("%s: failed to generate ospname (%d)\n",
qsd->qsd_svname, rc);
* up to usage; If usage < granted, release down to usage. */
for (type = USRQUOTA; type < MAXQUOTAS; type++) {
struct qsd_qtype_info *qqi = qsd->qsd_type_array[type];
- cfs_waitq_signal(&qqi->qqi_reint_thread.t_ctl_waitq);
+ wake_up(&qqi->qqi_reint_thread.t_ctl_waitq);
}
RETURN(rc);