+ cfs_down(&seq->lss_sem);
+ rc = __seq_server_alloc_super(seq, out, env);
+ cfs_up(&seq->lss_sem);
+
+ RETURN(rc);
+}
+
+static int __seq_set_init(const struct lu_env *env,
+ struct lu_server_seq *seq)
+{
+ struct lu_seq_range *space = &seq->lss_space;
+ int rc;
+
+ range_alloc(&seq->lss_lowater_set, space, seq->lss_set_width);
+ range_alloc(&seq->lss_hiwater_set, space, seq->lss_set_width);
+
+ rc = seq_store_update(env, seq, NULL, 1);
+ seq->lss_set_transno = 0;
+
+ return rc;
+}
+
+/*
+ * This function implements new seq allocation algorithm using async
+ * updates to seq file on disk. ref bug 18857 for details.
+ * there are four variable to keep track of this process
+ *
+ * lss_space; - available lss_space
+ * lss_lowater_set; - lu_seq_range for all seqs before barrier, i.e. safe to use
+ * lss_hiwater_set; - lu_seq_range after barrier, i.e. allocated but may be
+ * not yet committed
+ *
+ * when lss_lowater_set reaches the end it is replaced with hiwater one and
+ * a write operation is initiated to allocate new hiwater range.
+ * if last seq write opearion is still not commited, current operation is
+ * flaged as sync write op.
+ */
+static int range_alloc_set(const struct lu_env *env,
+ struct lu_seq_range *out,
+ struct lu_server_seq *seq)
+{
+ struct lu_seq_range *space = &seq->lss_space;
+ struct lu_seq_range *loset = &seq->lss_lowater_set;
+ struct lu_seq_range *hiset = &seq->lss_hiwater_set;
+ int rc = 0;
+
+ if (range_is_zero(loset))
+ __seq_set_init(env, seq);
+
+ if (OBD_FAIL_CHECK(OBD_FAIL_SEQ_ALLOC)) /* exhaust set */
+ loset->lsr_start = loset->lsr_end;
+
+ if (range_is_exhausted(loset)) {
+ /* reached high water mark. */
+ struct lu_device *dev = seq->lss_site->ms_lu.ls_top_dev;
+ struct lu_target *tg = dev->ld_obd->u.obt.obt_lut;
+ int obd_num_clients = dev->ld_obd->obd_num_exports;
+ __u64 set_sz;
+ int sync = 0;
+
+ /* calculate new seq width based on number of clients */
+ set_sz = max(seq->lss_set_width,
+ obd_num_clients * seq->lss_width);
+ set_sz = min(range_space(space), set_sz);
+
+ /* Switch to hiwater range now */
+ loset = hiset;
+ /* allocate new hiwater range */
+ range_alloc(hiset, space, set_sz);
+
+ if (seq->lss_set_transno > dev->ld_obd->obd_last_committed)
+ sync = 1;
+
+ /* update ondisk seq with new *space */
+ rc = seq_store_update(env, seq, NULL, sync);
+
+ /* set new hiwater transno */
+ cfs_spin_lock(&tg->lut_translock);
+ seq->lss_set_transno = tg->lut_last_transno;
+ cfs_spin_unlock(&tg->lut_translock);
+ }
+
+ LASSERTF(!range_is_exhausted(loset) || range_is_sane(loset),
+ DRANGE"\n", PRANGE(loset));
+
+ if (rc == 0)
+ range_alloc(out, loset, seq->lss_width);