- struct obd_statfs *msfs = &d->opd_statfs;
- int old = d->opd_pre_status;
- __u64 used;
-
- d->opd_pre_status = rc;
- if (rc)
- goto out;
-
- /* Add a bit of hysteresis so this flag isn't continually flapping,
- * and ensure that new files don't get extremely fragmented due to
- * only a small amount of available space in the filesystem.
- * We want to set the NOSPC flag when there is less than ~0.1% free
- * and clear it when there is at least ~0.2% free space, so:
- * avail < ~0.1% max max = avail + used
- * 1025 * avail < avail + used used = blocks - free
- * 1024 * avail < used
- * 1024 * avail < blocks - free
- * avail < ((blocks - free) >> 10)
- *
- * On very large disk, say 16TB 0.1% will be 16 GB. We don't want to
- * lose that amount of space so in those cases we report no space left
- * if their is less than 1 GB left. */
- if (likely(msfs->os_type)) {
- used = min_t(__u64, (msfs->os_blocks - msfs->os_bfree) >> 10,
- 1 << 30);
- if ((msfs->os_ffree < 32) || (msfs->os_bavail < used)) {
- d->opd_pre_status = -ENOSPC;
- if (old != -ENOSPC)
- CDEBUG(D_INFO, "%s: status: "LPU64" blocks, "
- LPU64" free, "LPU64" used, "LPU64" "
- "avail -> %d: rc = %d\n",
- d->opd_obd->obd_name, msfs->os_blocks,
- msfs->os_bfree, used, msfs->os_bavail,
- d->opd_pre_status, rc);
- CDEBUG(D_INFO,
- "non-commited changes: %lu, in progress: %u\n",
- d->opd_syn_changes, d->opd_syn_rpc_in_progress);
- } else if (old == -ENOSPC) {
- d->opd_pre_status = 0;
- d->opd_pre_grow_slow = 0;
- d->opd_pre_grow_count = OST_MIN_PRECREATE;
- cfs_waitq_signal(&d->opd_pre_waitq);
- CDEBUG(D_INFO, "%s: no space: "LPU64" blocks, "LPU64
- " free, "LPU64" used, "LPU64" avail -> %d: "
- "rc = %d\n", d->opd_obd->obd_name,
- msfs->os_blocks, msfs->os_bfree, used,
- msfs->os_bavail, d->opd_pre_status, rc);
+ u32 old_state = d->opd_statfs.os_state;
+ u32 reserved_ino_low = 32; /* could be tunable in the future */
+ u32 reserved_ino_high = reserved_ino_low * 2;
+ u64 available_mb;
+
+ /* statfs structure not initialized yet */
+ if (unlikely(!msfs->os_type))
+ return;
+
+ /* if the low and high watermarks have not been initialized yet */
+ if (unlikely(d->opd_reserved_mb_high == 0 &&
+ d->opd_reserved_mb_low == 0)) {
+ /* Use ~0.1% by default to disable object allocation,
+ * and ~0.2% to enable, size in MB, set both watermark
+ */
+ spin_lock(&d->opd_pre_lock);
+ if (d->opd_reserved_mb_high == 0 &&
+ d->opd_reserved_mb_low == 0) {
+ d->opd_reserved_mb_low = ((msfs->os_bsize >> 10) *
+ msfs->os_blocks) >> 20;
+ if (d->opd_reserved_mb_low == 0)
+ d->opd_reserved_mb_low = 1;
+ d->opd_reserved_mb_high =
+ (d->opd_reserved_mb_low << 1) + 1;