Whamcloud - gitweb
LU-10602 llite: add file heat support
[fs/lustre-release.git] / lustre / llite / file.c
index b429b2b..33da782 100644 (file)
@@ -1369,6 +1369,37 @@ static void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot)
        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,
@@ -1499,6 +1530,8 @@ out:
        }
 
        CDEBUG(D_VFSTRACE, "iot: %d, result: %zd\n", iot, result);
+       if (result > 0)
+               ll_heat_add(inode, iot, result);
 
        RETURN(result > 0 ? result : rc);
 }
@@ -1559,9 +1592,11 @@ ll_do_fast_read(struct kiocb *iocb, struct iov_iter *iter)
        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;
 }
@@ -1649,6 +1684,7 @@ static ssize_t ll_do_tiny_write(struct kiocb *iocb, struct iov_iter *iter)
                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);
@@ -3238,6 +3274,41 @@ static long ll_file_set_lease(struct file *file, struct ll_ioc_lease *ioc,
        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)
 {
@@ -3621,6 +3692,37 @@ out_ladvise:
                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));