GOTO(cleanup, rc);
/*
* decay extent blocks if we could allocate
- * good large(1M) extent.
+ * good large extent.
*/
- if (previous_total == 0 &&
- total >= OSD_DEFAULT_EXTENT_BYTES >> inode->i_blkbits)
+ if (total - previous_total >=
+ osd_extent_bytes(osd) >> inode->i_blkbits)
osd_decay_extent_bytes(osd,
- total << inode->i_blkbits);
+ (total - previous_total) << inode->i_blkbits);
/* look for next extent */
fp = NULL;
blocks += blocks_per_page * clen;
return cached_extent->mapped;
}
+#define MAX_EXTENTS_PER_WRITE 100
static int osd_declare_write_commit(const struct lu_env *env,
struct dt_object *dt,
struct niobuf_local *lnb, int npages,
if (lnb[i].lnb_file_offset != extent.end || extent.end == 0) {
if (extent.end != 0)
extents += (extent.end - extent.start +
- extent_bytes - 1) / extent_bytes;
+ extent_bytes - 1) / extent_bytes;
extent.start = lnb[i].lnb_file_offset;
extent.end = lnb[i].lnb_file_offset + lnb[i].lnb_len;
} else {
extents += (extent.end - extent.start +
extent_bytes - 1) / extent_bytes;
+ /**
+ * with system space usage growing up, mballoc codes won't
+ * try best to scan block group to align best free extent as
+ * we can. So extent bytes per extent could be decayed to a
+ * very small value, this could make us reserve too many credits.
+ * We could be more optimistic in the credit reservations, even
+ * in a case where the filesystem is nearly full, it is extremely
+ * unlikely that the worst case would ever be hit.
+ */
+ if (extents > MAX_EXTENTS_PER_WRITE)
+ extents = MAX_EXTENTS_PER_WRITE;
+
/*
* each extent can go into new leaf causing a split
* 5 is max tree depth: inode + 4 index blocks
else
credits += extents;
+ CDEBUG(D_INODE,
+ "%s: inode #%lu extent_bytes %u extents %d credits %d\n",
+ osd_ino2name(inode), inode->i_ino, extent_bytes, extents,
+ credits);
+
out_declare:
osd_trans_declare_op(env, oh, OSD_OT_WRITE, credits);
}
LUSTRE_RW_ATTR(full_scrub_threshold_rate);
+static ssize_t extent_bytes_allocation_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct dt_device *dt = container_of(kobj, struct dt_device,
+ dd_kobj);
+ struct osd_device *dev = osd_dt_dev(dt);
+ int i;
+ unsigned int min = (unsigned int)(~0), cur;
+
+ for_each_online_cpu(i) {
+ cur = *per_cpu_ptr(dev->od_extent_bytes_percpu, i);
+ if (cur < min)
+ min = cur;
+ }
+ return snprintf(buf, PAGE_SIZE, "%u\n", min);
+}
+LUSTRE_RO_ATTR(extent_bytes_allocation);
+
static int ldiskfs_osd_oi_scrub_seq_show(struct seq_file *m, void *data)
{
struct osd_device *dev = osd_dt_dev((struct dt_device *)m->private);
&lustre_attr_pdo.attr,
&lustre_attr_full_scrub_ratio.attr,
&lustre_attr_full_scrub_threshold_rate.attr,
+ &lustre_attr_extent_bytes_allocation.attr,
NULL,
};