ll_io_set_mirror(io, file);
}
+static void ll_heat_add(struct inode *inode, enum cl_io_type iot,
+ __u64 count)
+{
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ enum obd_heat_type sample_type;
+ enum obd_heat_type iobyte_type;
+ __u64 now = ktime_get_real_seconds();
+
+ if (!ll_sbi_has_file_heat(sbi) ||
+ lli->lli_heat_flags & LU_HEAT_FLAG_OFF)
+ return;
+
+ if (iot == CIT_READ) {
+ sample_type = OBD_HEAT_READSAMPLE;
+ iobyte_type = OBD_HEAT_READBYTE;
+ } else if (iot == CIT_WRITE) {
+ sample_type = OBD_HEAT_WRITESAMPLE;
+ iobyte_type = OBD_HEAT_WRITEBYTE;
+ } else {
+ return;
+ }
+
+ spin_lock(&lli->lli_heat_lock);
+ obd_heat_add(&lli->lli_heat_instances[sample_type], now, 1,
+ sbi->ll_heat_decay_weight, sbi->ll_heat_period_second);
+ obd_heat_add(&lli->lli_heat_instances[iobyte_type], now, count,
+ sbi->ll_heat_decay_weight, sbi->ll_heat_period_second);
+ spin_unlock(&lli->lli_heat_lock);
+}
+
static ssize_t
ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
struct file *file, enum cl_io_type iot,
}
CDEBUG(D_VFSTRACE, "iot: %d, result: %zd\n", iot, result);
+ if (result > 0)
+ ll_heat_add(inode, iot, result);
RETURN(result > 0 ? result : rc);
}
if (result == -ENODATA)
result = 0;
- if (result > 0)
+ if (result > 0) {
+ ll_heat_add(file_inode(iocb->ki_filp), CIT_READ, result);
ll_stats_ops_tally(ll_i2sbi(file_inode(iocb->ki_filp)),
LPROC_LL_READ_BYTES, result);
+ }
return result;
}
result = 0;
if (result > 0) {
+ ll_heat_add(inode, CIT_WRITE, result);
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_WRITE_BYTES,
result);
ll_file_set_flag(ll_i2info(inode), LLIF_DATA_MODIFIED);
RETURN(rc);
}
+static void ll_heat_get(struct inode *inode, struct lu_heat *heat)
+{
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ __u64 now = ktime_get_real_seconds();
+ int i;
+
+ spin_lock(&lli->lli_heat_lock);
+ heat->lh_flags = lli->lli_heat_flags;
+ for (i = 0; i < heat->lh_count; i++)
+ heat->lh_heat[i] = obd_heat_get(&lli->lli_heat_instances[i],
+ now, sbi->ll_heat_decay_weight,
+ sbi->ll_heat_period_second);
+ spin_unlock(&lli->lli_heat_lock);
+}
+
+static int ll_heat_set(struct inode *inode, __u64 flags)
+{
+ struct ll_inode_info *lli = ll_i2info(inode);
+ int rc = 0;
+
+ spin_lock(&lli->lli_heat_lock);
+ if (flags & LU_HEAT_FLAG_CLEAR)
+ obd_heat_clear(lli->lli_heat_instances, OBD_HEAT_COUNT);
+
+ if (flags & LU_HEAT_FLAG_OFF)
+ lli->lli_heat_flags |= LU_HEAT_FLAG_OFF;
+ else
+ lli->lli_heat_flags &= ~LU_HEAT_FLAG_OFF;
+
+ spin_unlock(&lli->lli_heat_lock);
+
+ RETURN(rc);
+}
+
static long
ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
RETURN(ll_ioctl_fssetxattr(inode, cmd, arg));
case BLKSSZGET:
RETURN(put_user(PAGE_SIZE, (int __user *)arg));
+ case LL_IOC_HEAT_GET: {
+ struct lu_heat uheat;
+ struct lu_heat *heat;
+ int size;
+
+ if (copy_from_user(&uheat, (void __user *)arg, sizeof(uheat)))
+ RETURN(-EFAULT);
+
+ if (uheat.lh_count > OBD_HEAT_COUNT)
+ uheat.lh_count = OBD_HEAT_COUNT;
+
+ size = offsetof(typeof(uheat), lh_heat[uheat.lh_count]);
+ OBD_ALLOC(heat, size);
+ if (heat == NULL)
+ RETURN(-ENOMEM);
+
+ heat->lh_count = uheat.lh_count;
+ ll_heat_get(inode, heat);
+ rc = copy_to_user((char __user *)arg, heat, size);
+ OBD_FREE(heat, size);
+ RETURN(rc ? -EFAULT : 0);
+ }
+ case LL_IOC_HEAT_SET: {
+ __u64 flags;
+
+ if (copy_from_user(&flags, (void __user *)arg, sizeof(flags)))
+ RETURN(-EFAULT);
+
+ rc = ll_heat_set(inode, flags);
+ RETURN(rc);
+ }
default:
RETURN(obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL,
(void __user *)arg));