[PATCH v4] perf record: Add support for limit perf output file size

2019-09-25 Thread Jiwei Sun
The patch adds a new option to limit the output file size, then based
on it, we can create a wrapper of the perf command that uses the option
to avoid exhausting the disk space by the unconscious user.

In order to make the perf.data parsable, we just limit the sample data
size, since the perf.data consists of many headers and sample data and
other data, the actual size of the recorded file will bigger than the
setting value.

Testing it:

 # ./perf record -a -g --max-size=10M
Couldn't synthesize bpf events.
WARNING: The perf data has already reached the limit, stop recording!
[ perf record: Woken up 30 times to write data ]
[ perf record: Captured and wrote 10.233 MB perf.data (175650 samples) ]
Terminated

 # ls -lh perf.data
-rw--- 1 root root 11M Jul 17 14:01 perf.data

 # ./perf record -a -g --max-size=10K
WARNING: The perf data has already reached the limit, stop recording!
Couldn't synthesize bpf events.
[ perf record: Woken up 0 times to write data ]
[ perf record: Captured and wrote 1.824 MB perf.data (67 samples) ]
Terminated

 # ls -lh perf.data
-rw--- 1 root root 1.9M Jul 17 14:05 perf.data

Signed-off-by: Jiwei Sun 
---
v4 changes:
  - Just show one WARNING message after reached the limit.

v3 changes:
  - add a test result
  - add the new option to tools/perf/Documentation/perf-record.txt

v2 changes:
  - make patch based on latest Arnaldo's perf/core,
  - display warning message when reached the limit.
---
 tools/perf/Documentation/perf-record.txt |  4 +++
 tools/perf/builtin-record.c  | 42 
 2 files changed, 46 insertions(+)

diff --git a/tools/perf/Documentation/perf-record.txt 
b/tools/perf/Documentation/perf-record.txt
index c6f9f31b6039..f1c6113fbc82 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -571,6 +571,10 @@ config terms. For example: 'cycles/overwrite/' and 
'instructions/no-overwrite/'.
 
 Implies --tail-synthesize.
 
+--max-size=::
+Limit the sample data max size,  is expected to be a number with
+appended unit character - B/K/M/G
+
 SEE ALSO
 
 linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 48600c90cc7e..30904d2a3407 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -91,6 +91,7 @@ struct record {
struct switch_outputswitch_output;
unsigned long long  samples;
cpu_set_t   affinity_mask;
+   unsigned long   output_max_size;/* = 0: unlimited */
 };
 
 static volatile int auxtrace_record__snapshot_started;
@@ -120,6 +121,12 @@ static bool switch_output_time(struct record *rec)
   trigger_is_ready(&switch_output_trigger);
 }
 
+static bool record__output_max_size_exceeded(struct record *rec)
+{
+   return rec->output_max_size &&
+  (rec->bytes_written >= rec->output_max_size);
+}
+
 static int record__write(struct record *rec, struct mmap *map __maybe_unused,
 void *bf, size_t size)
 {
@@ -132,6 +139,12 @@ static int record__write(struct record *rec, struct mmap 
*map __maybe_unused,
 
rec->bytes_written += size;
 
+   if (record__output_max_size_exceeded(rec)) {
+   WARN_ONCE(1, "WARNING: The perf data has already reached "
+"the limit, stop recording!\n");
+   raise(SIGTERM);
+   }
+
if (switch_output_size(rec))
trigger_hit(&switch_output_trigger);
 
@@ -1936,6 +1949,33 @@ static int record__parse_affinity(const struct option 
*opt, const char *str, int
return 0;
 }
 
+static int parse_output_max_size(const struct option *opt,
+const char *str, int unset)
+{
+   unsigned long *s = (unsigned long *)opt->value;
+   static struct parse_tag tags_size[] = {
+   { .tag  = 'B', .mult = 1   },
+   { .tag  = 'K', .mult = 1 << 10 },
+   { .tag  = 'M', .mult = 1 << 20 },
+   { .tag  = 'G', .mult = 1 << 30 },
+   { .tag  = 0 },
+   };
+   unsigned long val;
+
+   if (unset) {
+   *s = 0;
+   return 0;
+   }
+
+   val = parse_tag_value(str, tags_size);
+   if (val != (unsigned long) -1) {
+   *s = val;
+   return 0;
+   }
+
+   return -1;
+}
+
 static int record__parse_mmap_pages(const struct option *opt,
const char *str,
int unset __maybe_unused)
@@ -2262,6 +2302,8 @@ static struct option __record_options[] = {
"n", "Compressed records using specified level 
(default: 1 - fastest compression, 22 - greatest compression)",

[PATCH v4] perf record: Add support for limit perf output file size

2019-07-17 Thread Jiwei Sun
The patch adds a new option to limit the output file size, then based
on it, we can create a wrapper of the perf command that uses the option
to avoid exhausting the disk space by the unconscious user.

In order to make the perf.data parsable, we just limit the sample data
size, since the perf.data consists of many headers and sample data and
other data, the actual size of the recorded file will bigger than the
setting value.

Testing it:

 # ./perf record -a -g --max-size=10M
Couldn't synthesize bpf events.
WARNING: The perf data has already reached the limit, stop recording!
[ perf record: Woken up 30 times to write data ]
[ perf record: Captured and wrote 10.233 MB perf.data (175650 samples) ]
Terminated

 # ls -lh perf.data
-rw--- 1 root root 11M Jul 17 14:01 perf.data

 # ./perf record -a -g --max-size=10K
WARNING: The perf data has already reached the limit, stop recording!
Couldn't synthesize bpf events.
[ perf record: Woken up 0 times to write data ]
[ perf record: Captured and wrote 1.824 MB perf.data (67 samples) ]
Terminated

 # ls -lh perf.data
-rw--- 1 root root 1.9M Jul 17 14:05 perf.data

Signed-off-by: Jiwei Sun 
---
v4 changes:
  - Just show one WARNING message after reached the limit.

v3 changes:
  - add a test result
  - add the new option to tools/perf/Documentation/perf-record.txt

v2 changes:
  - make patch based on latest Arnaldo's perf/core,
  - display warning message when reached the limit.
---
 tools/perf/Documentation/perf-record.txt |  4 +++
 tools/perf/builtin-record.c  | 42 
 2 files changed, 46 insertions(+)

diff --git a/tools/perf/Documentation/perf-record.txt 
b/tools/perf/Documentation/perf-record.txt
index 15e0fa87241b..918a0844cbcf 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -564,6 +564,10 @@ config terms. For example: 'cycles/overwrite/' and 
'instructions/no-overwrite/'.
 
 Implies --tail-synthesize.
 
+--max-size=::
+Limit the sample data max size,  is expected to be a number with
+appended unit character - B/K/M/G
+
 SEE ALSO
 
 linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8779cee58185..8c49dce3abd8 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -86,6 +86,7 @@ struct record {
struct switch_outputswitch_output;
unsigned long long  samples;
cpu_set_t   affinity_mask;
+   unsigned long   output_max_size;/* = 0: unlimited */
 };
 
 static volatile int auxtrace_record__snapshot_started;
@@ -115,6 +116,12 @@ static bool switch_output_time(struct record *rec)
   trigger_is_ready(&switch_output_trigger);
 }
 
+static bool record__output_max_size_exceeded(struct record *rec)
+{
+   return (rec->output_max_size &&
+  rec->bytes_written >= rec->output_max_size);
+}
+
 static int record__write(struct record *rec, struct perf_mmap *map 
__maybe_unused,
 void *bf, size_t size)
 {
@@ -127,6 +134,12 @@ static int record__write(struct record *rec, struct 
perf_mmap *map __maybe_unuse
 
rec->bytes_written += size;
 
+   if (record__output_max_size_exceeded(rec)) {
+   WARN_ONCE(1, "WARNING: The perf data has already reached "
+"the limit, stop recording!\n");
+   raise(SIGTERM);
+   }
+
if (switch_output_size(rec))
trigger_hit(&switch_output_trigger);
 
@@ -1902,6 +1915,33 @@ static int record__parse_affinity(const struct option 
*opt, const char *str, int
return 0;
 }
 
+static int parse_output_max_size(const struct option *opt,
+const char *str, int unset)
+{
+   unsigned long *s = (unsigned long *)opt->value;
+   static struct parse_tag tags_size[] = {
+   { .tag  = 'B', .mult = 1   },
+   { .tag  = 'K', .mult = 1 << 10 },
+   { .tag  = 'M', .mult = 1 << 20 },
+   { .tag  = 'G', .mult = 1 << 30 },
+   { .tag  = 0 },
+   };
+   unsigned long val;
+
+   if (unset) {
+   *s = 0;
+   return 0;
+   }
+
+   val = parse_tag_value(str, tags_size);
+   if (val != (unsigned long) -1) {
+   *s = val;
+   return 0;
+   }
+
+   return -1;
+}
+
 static int record__parse_mmap_pages(const struct option *opt,
const char *str,
int unset __maybe_unused)
@@ -2228,6 +2268,8 @@ static struct option __record_options[] = {
"n", "Compressed records using specified level 
(default: 1 - fastest compression, 22 - greatest compression)&quo

Re: [PATCH v4] perf record: Add support for limit perf output file size

2019-10-21 Thread Jiwei Sun
Hello Arnaldo & Jirka,

Do you have any other suggestions regarding the patch? 
Any suggestions are welcome. Thank you very much.

Regards,
Jiwei

On 2019e9409f25f% 15:06, Jiwei Sun wrote:
> The patch adds a new option to limit the output file size, then based
> on it, we can create a wrapper of the perf command that uses the option
> to avoid exhausting the disk space by the unconscious user.
> 
> In order to make the perf.data parsable, we just limit the sample data
> size, since the perf.data consists of many headers and sample data and
> other data, the actual size of the recorded file will bigger than the
> setting value.
> 
> Testing it:
> 
>  # ./perf record -a -g --max-size=10M
> Couldn't synthesize bpf events.
> WARNING: The perf data has already reached the limit, stop recording!
> [ perf record: Woken up 30 times to write data ]
> [ perf record: Captured and wrote 10.233 MB perf.data (175650 samples) ]
> Terminated
> 
>  # ls -lh perf.data
> -rw--- 1 root root 11M Jul 17 14:01 perf.data
> 
>  # ./perf record -a -g --max-size=10K
> WARNING: The perf data has already reached the limit, stop recording!
> Couldn't synthesize bpf events.
> [ perf record: Woken up 0 times to write data ]
> [ perf record: Captured and wrote 1.824 MB perf.data (67 samples) ]
> Terminated
> 
>  # ls -lh perf.data
> -rw--- 1 root root 1.9M Jul 17 14:05 perf.data
> 
> Signed-off-by: Jiwei Sun 
> ---
> v4 changes:
>   - Just show one WARNING message after reached the limit.
> 
> v3 changes:
>   - add a test result
>   - add the new option to tools/perf/Documentation/perf-record.txt
> 
> v2 changes:
>   - make patch based on latest Arnaldo's perf/core,
>   - display warning message when reached the limit.
> ---
>  tools/perf/Documentation/perf-record.txt |  4 +++
>  tools/perf/builtin-record.c  | 42 
>  2 files changed, 46 insertions(+)
> 
> diff --git a/tools/perf/Documentation/perf-record.txt 
> b/tools/perf/Documentation/perf-record.txt
> index c6f9f31b6039..f1c6113fbc82 100644
> --- a/tools/perf/Documentation/perf-record.txt
> +++ b/tools/perf/Documentation/perf-record.txt
> @@ -571,6 +571,10 @@ config terms. For example: 'cycles/overwrite/' and 
> 'instructions/no-overwrite/'.
>  
>  Implies --tail-synthesize.
>  
> +--max-size=::
> +Limit the sample data max size,  is expected to be a number with
> +appended unit character - B/K/M/G
> +
>  SEE ALSO
>  
>  linkperf:perf-stat[1], linkperf:perf-list[1]
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 48600c90cc7e..30904d2a3407 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -91,6 +91,7 @@ struct record {
>   struct switch_outputswitch_output;
>   unsigned long long  samples;
>   cpu_set_t   affinity_mask;
> + unsigned long   output_max_size;/* = 0: unlimited */
>  };
>  
>  static volatile int auxtrace_record__snapshot_started;
> @@ -120,6 +121,12 @@ static bool switch_output_time(struct record *rec)
>  trigger_is_ready(&switch_output_trigger);
>  }
>  
> +static bool record__output_max_size_exceeded(struct record *rec)
> +{
> + return rec->output_max_size &&
> +(rec->bytes_written >= rec->output_max_size);
> +}
> +
>  static int record__write(struct record *rec, struct mmap *map __maybe_unused,
>void *bf, size_t size)
>  {
> @@ -132,6 +139,12 @@ static int record__write(struct record *rec, struct mmap 
> *map __maybe_unused,
>  
>   rec->bytes_written += size;
>  
> + if (record__output_max_size_exceeded(rec)) {
> + WARN_ONCE(1, "WARNING: The perf data has already reached "
> +  "the limit, stop recording!\n");
> + raise(SIGTERM);
> + }
> +
>   if (switch_output_size(rec))
>   trigger_hit(&switch_output_trigger);
>  
> @@ -1936,6 +1949,33 @@ static int record__parse_affinity(const struct option 
> *opt, const char *str, int
>   return 0;
>  }
>  
> +static int parse_output_max_size(const struct option *opt,
> +  const char *str, int unset)
> +{
> + unsigned long *s = (unsigned long *)opt->value;
> + static struct parse_tag tags_size[] = {
> + { .tag  = 'B', .mult = 1   },
> + { .tag  = 'K', .mult = 1 << 10 },
> + { .tag  = 'M', .mult = 1 << 20 },
> + { .tag  = 'G', .mult = 1 << 30 }

Re: [PATCH v4] perf record: Add support for limit perf output file size

2019-10-21 Thread Jiwei Sun
Hi Jirka,

On 2019e9410f21f% 21:41, Jiri Olsa wrote:
> On Wed, Sep 25, 2019 at 03:06:37PM +0800, Jiwei Sun wrote:
> 
> SNIP
> 
>>  SEE ALSO
>>  
>>  linkperf:perf-stat[1], linkperf:perf-list[1]
>> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
>> index 48600c90cc7e..30904d2a3407 100644
>> --- a/tools/perf/builtin-record.c
>> +++ b/tools/perf/builtin-record.c
>> @@ -91,6 +91,7 @@ struct record {
>>  struct switch_outputswitch_output;
>>  unsigned long long  samples;
>>  cpu_set_t   affinity_mask;
>> +unsigned long   output_max_size;/* = 0: unlimited */
>>  };
>>  
>>  static volatile int auxtrace_record__snapshot_started;
>> @@ -120,6 +121,12 @@ static bool switch_output_time(struct record *rec)
>> trigger_is_ready(&switch_output_trigger);
>>  }
>>  
>> +static bool record__output_max_size_exceeded(struct record *rec)
>> +{
>> +return rec->output_max_size &&
>> +   (rec->bytes_written >= rec->output_max_size);
>> +}
>> +
>>  static int record__write(struct record *rec, struct mmap *map 
>> __maybe_unused,
>>   void *bf, size_t size)
>>  {
>> @@ -132,6 +139,12 @@ static int record__write(struct record *rec, struct 
>> mmap *map __maybe_unused,
>>  
>>  rec->bytes_written += size;
>>  
>> +if (record__output_max_size_exceeded(rec)) {
>> +WARN_ONCE(1, "WARNING: The perf data has already reached "
>> + "the limit, stop recording!\n");
> 
> I think the message whouldn't be a warning, the user asked for
> that, maybe something more like:
> 
>   [ perf record: perf size limit reached (XXMB), stopping session ]
> 
>> +raise(SIGTERM);
> 
> could we just set 'done = 1' what's the benefit in killing perf?

Thanks for your suggestions. Yes, if just set "done == 1" is more efficient and 
more concise.
And I will modify it and the output format, and then send a v5 patch.
Thanks again.

Regards,
Jiwei

> 
> thanks,
> jirka
> 
> 


[PATCH] perf record: Add support for limit perf output file size

2019-02-20 Thread Jiwei Sun
The patch adds a new option to limit the output file size, then based
on it, we can create a wrapper of the perf command that uses the option
to avoid exhausting the disk space by the unconscious user.

Signed-off-by: Jiwei Sun 
---
 tools/perf/builtin-record.c | 39 +
 1 file changed, 39 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 882285fb9f64..28a03929166d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -81,6 +81,7 @@ struct record {
booltimestamp_boundary;
struct switch_outputswitch_output;
unsigned long long  samples;
+   unsigned long   output_max_size;/* = 0: unlimited */
 };
 
 static volatile int auxtrace_record__snapshot_started;
@@ -106,6 +107,12 @@ static bool switch_output_time(struct record *rec)
   trigger_is_ready(&switch_output_trigger);
 }
 
+static bool record__output_max_size_exceeded(struct record *rec)
+{
+   return (rec->output_max_size &&
+   rec->bytes_written >= rec->output_max_size);
+}
+
 static int record__write(struct record *rec, struct perf_mmap *map 
__maybe_unused,
 void *bf, size_t size)
 {
@@ -118,6 +125,9 @@ static int record__write(struct record *rec, struct 
perf_mmap *map __maybe_unuse
 
rec->bytes_written += size;
 
+   if (record__output_max_size_exceeded(rec))
+   raise(SIGTERM);
+
if (switch_output_size(rec))
trigger_hit(&switch_output_trigger);
 
@@ -1639,6 +1649,33 @@ static int parse_clockid(const struct option *opt, const 
char *str, int unset)
return -1;
 }
 
+static int parse_output_max_size(const struct option *opt, const char *str,
+int unset)
+{
+   unsigned long *s = (unsigned long *)opt->value;
+   static struct parse_tag tags_size[] = {
+   { .tag  = 'B', .mult = 1   },
+   { .tag  = 'K', .mult = 1 << 10 },
+   { .tag  = 'M', .mult = 1 << 20 },
+   { .tag  = 'G', .mult = 1 << 30 },
+   { .tag  = 0 },
+   };
+   unsigned long val;
+
+   if (unset) {
+   *s = 0;
+   return 0;
+   }
+
+   val = parse_tag_value(str, tags_size);
+   if (val != (unsigned long) -1) {
+   *s = val;
+   return 0;
+   }
+
+   return -1;
+}
+
 static int record__parse_mmap_pages(const struct option *opt,
const char *str,
int unset __maybe_unused)
@@ -1946,6 +1983,8 @@ static struct option __record_options[] = {
 &nr_cblocks_default, "n", "Use  control blocks in 
asynchronous trace writing mode (default: 1, max: 4)",
 record__aio_parse),
 #endif
+   OPT_CALLBACK(0, "output-max-size", &record.output_max_size,
+"size", "Output file maximum size", parse_output_max_size),
OPT_END()
 };
 
-- 
2.20.1



[PATCH]spi: pl022: add a message state STATE_TIMEOUT for timeout transfer

2019-01-17 Thread Jiwei Sun
When transfer timeout, give -EAGAIN to the message's status, and it can
make the spi device driver choose repeated transimation or not. And if
transfer timeout, output some useful information for tracing the issue.

Signed-off-by: Jiwei Sun 
---
 drivers/spi/spi-pl022.c | 30 +-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 0c793e31d60f..26684178786f 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -253,6 +253,7 @@
 #define STATE_RUNNING  ((void *) 1)
 #define STATE_DONE ((void *) 2)
 #define STATE_ERROR((void *) -1)
+#define STATE_TIMEOUT  ((void *) -2)
 
 /*
  * SSP State - Whether Enabled or Disabled
@@ -1484,6 +1485,30 @@ static void do_interrupt_dma_transfer(struct pl022 
*pl022)
writew(irqflags, SSP_IMSC(pl022->virtbase));
 }
 
+static void print_current_status(struct pl022 *pl022)
+{
+   u32 read_cr0;
+   u16 read_cr1, read_dmacr, read_sr;
+
+   if (pl022->vendor->extended_cr)
+   read_cr0 = readl(SSP_CR0(pl022->virtbase));
+   else
+   read_cr0 = readw(SSP_CR0(pl022->virtbase));
+   read_cr1 = readw(SSP_CR1(pl022->virtbase));
+   read_dmacr = readw(SSP_DMACR(pl022->virtbase));
+   read_sr = readw(SSP_SR(pl022->virtbase));
+
+   dev_warn(&pl022->adev->dev, "spi-pl022 CR0: %x\n", read_cr0);
+   dev_warn(&pl022->adev->dev, "spi-pl022 CR1: %x\n", read_cr1);
+   dev_warn(&pl022->adev->dev, "spi-pl022 DMACR: %x\n", read_dmacr);
+   dev_warn(&pl022->adev->dev, "spi-pl022 SR: %x\n", read_sr);
+   dev_warn(&pl022->adev->dev,
+   "spi-pl022 exp_fifo_level/fifodepth: %u/%d\n",
+   pl022->exp_fifo_level,
+   pl022->vendor->fifodepth);
+
+}
+
 static void do_polling_transfer(struct pl022 *pl022)
 {
struct spi_message *message = NULL;
@@ -1535,7 +1560,8 @@ static void do_polling_transfer(struct pl022 *pl022)
if (time_after(time, timeout)) {
dev_warn(&pl022->adev->dev,
"%s: timeout!\n", __func__);
-   message->state = STATE_ERROR;
+   message->state = STATE_TIMEOUT;
+   print_current_status(pl022);
goto out;
}
cpu_relax();
@@ -1553,6 +1579,8 @@ static void do_polling_transfer(struct pl022 *pl022)
/* Handle end of message */
if (message->state == STATE_DONE)
message->status = 0;
+   else if (message->state == STATE_TIMEOUT)
+   message->status = -EAGAIN;
else
message->status = -EIO;
 
-- 
2.20.1



[PATCH v3] perf record: Add support for limit perf output file size

2019-03-11 Thread Jiwei Sun
The patch adds a new option to limit the output file size, then based
on it, we can create a wrapper of the perf command that uses the option
to avoid exhausting the disk space by the unconscious user.

Testing it:

  # ./perf record -a --max-size 100M
  Couldn't synthesize bpf events.
  WARNING: The perf data has already reached the limit, stop recording!
  WARNING: The perf data has already reached the limit, stop recording!
  WARNING: The perf data has already reached the limit, stop recording!
  WARNING: The perf data has already reached the limit, stop recording!
  WARNING: The perf data has already reached the limit, stop recording!
  WARNING: The perf data has already reached the limit, stop recording!
  WARNING: The perf data has already reached the limit, stop recording!
  WARNING: The perf data has already reached the limit, stop recording!
  [ perf record: Woken up 392 times to write data ]
  [ perf record: Captured and wrote 100.104 MB perf.data (2128267 samples) ]
  Terminated

  # ls -lh perf.data
  -rw--- 1 root root 101M Mar 11 14:48 perf.data

Signed-off-by: Jiwei Sun 
---
v3 changes:
  - add a test result
  - add the new option to tools/perf/Documentation/perf-record.txt

v2 changes:
  - make patch based on latest Arnaldo's perf/core,
  - display warning message when reached the limit.
---
 tools/perf/Documentation/perf-record.txt |  3 ++
 tools/perf/builtin-record.c  | 42 
 2 files changed, 45 insertions(+)

diff --git a/tools/perf/Documentation/perf-record.txt 
b/tools/perf/Documentation/perf-record.txt
index 8f0c2be34848..731dcfabe7fa 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -524,6 +524,9 @@ config terms. For example: 'cycles/overwrite/' and 
'instructions/no-overwrite/'.
 
 Implies --tail-synthesize.
 
+--max-size::
+Limit the output data max size.
+
 SEE ALSO
 
 linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a468d882e74f..fe0e87781841 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -83,6 +83,7 @@ struct record {
struct switch_outputswitch_output;
unsigned long long  samples;
cpu_set_t   affinity_mask;
+   unsigned long   output_max_size;/* = 0: unlimited */
 };
 
 static volatile int auxtrace_record__snapshot_started;
@@ -112,6 +113,12 @@ static bool switch_output_time(struct record *rec)
   trigger_is_ready(&switch_output_trigger);
 }
 
+static bool record__output_max_size_exceeded(struct record *rec)
+{
+   return (rec->output_max_size &&
+  rec->bytes_written >= rec->output_max_size);
+}
+
 static int record__write(struct record *rec, struct perf_mmap *map 
__maybe_unused,
 void *bf, size_t size)
 {
@@ -124,6 +131,12 @@ static int record__write(struct record *rec, struct 
perf_mmap *map __maybe_unuse
 
rec->bytes_written += size;
 
+   if (record__output_max_size_exceeded(rec)) {
+   pr_warning("WARNING: The perf data has already reached "
+  "the limit, stop recording!\n");
+   raise(SIGTERM);
+   }
+
if (switch_output_size(rec))
trigger_hit(&switch_output_trigger);
 
@@ -1672,6 +1685,33 @@ static int record__parse_affinity(const struct option 
*opt, const char *str, int
return 0;
 }
 
+static int parse_output_max_size(const struct option *opt,
+const char *str, int unset)
+{
+   unsigned long *s = (unsigned long *)opt->value;
+   static struct parse_tag tags_size[] = {
+   { .tag  = 'B', .mult = 1   },
+   { .tag  = 'K', .mult = 1 << 10 },
+   { .tag  = 'M', .mult = 1 << 20 },
+   { .tag  = 'G', .mult = 1 << 30 },
+   { .tag  = 0 },
+   };
+   unsigned long val;
+
+   if (unset) {
+   *s = 0;
+   return 0;
+   }
+
+   val = parse_tag_value(str, tags_size);
+   if (val != (unsigned long) -1) {
+   *s = val;
+   return 0;
+   }
+
+   return -1;
+}
+
 static int record__parse_mmap_pages(const struct option *opt,
const char *str,
int unset __maybe_unused)
@@ -1983,6 +2023,8 @@ static struct option __record_options[] = {
OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu",
 "Set affinity mask of trace reading thread to NUMA node 
cpu mask or cpu of processed mmap buffer",
 record__parse_affinity),
+   OPT_CALLBACK(0, "max-size", &record.output_max_size,
+"size", "Limit the maximum size of the output file", 
parse_output_max_size),
OPT_END()
 };
 
-- 
2.20.1



Re: [PATCH] perf record: Add support for limit perf output file size

2019-02-21 Thread Jiwei Sun
Hi Jirka,

On 02/21/2019 05:56 PM, Jiri Olsa wrote:
> On Thu, Feb 21, 2019 at 02:44:19PM +0800, Jiwei Sun wrote:
>> The patch adds a new option to limit the output file size, then based
>> on it, we can create a wrapper of the perf command that uses the option
>> to avoid exhausting the disk space by the unconscious user.
>>
>> Signed-off-by: Jiwei Sun 
>> ---
>>  tools/perf/builtin-record.c | 39 +
>>  1 file changed, 39 insertions(+)
>>
>> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
>> index 882285fb9f64..28a03929166d 100644
>> --- a/tools/perf/builtin-record.c
>> +++ b/tools/perf/builtin-record.c
>> @@ -81,6 +81,7 @@ struct record {
>>  booltimestamp_boundary;
>>  struct switch_outputswitch_output;
>>  unsigned long long  samples;
>> +unsigned long   output_max_size;/* = 0: unlimited */
> 
> please rebase to latest Arnaldo's perf/core,
> there are new fields in here now

OK, thanks for your response, and I will send a v2 patch based on the branch 
perf/core.

> 
>>  };
>>  
>>  static volatile int auxtrace_record__snapshot_started;
>> @@ -106,6 +107,12 @@ static bool switch_output_time(struct record *rec)
>> trigger_is_ready(&switch_output_trigger);
>>  }
>>  
>> +static bool record__output_max_size_exceeded(struct record *rec)
>> +{
>> +return (rec->output_max_size &&
>> +rec->bytes_written >= rec->output_max_size);
>> +}
>> +
>>  static int record__write(struct record *rec, struct perf_mmap *map 
>> __maybe_unused,
>>   void *bf, size_t size)
>>  {
>> @@ -118,6 +125,9 @@ static int record__write(struct record *rec, struct 
>> perf_mmap *map __maybe_unuse
>>  
>>  rec->bytes_written += size;
>>  
>> +if (record__output_max_size_exceeded(rec))
>> +raise(SIGTERM);
> 
> perhaps display some message saying we reached the limit
> 
> other than that looks good to me

OK, I will add some warning message in the v2 patch.

Thanks,
Regards,
Jiwei

> 
> thanks,
> jirka
> 
> 
>> +
>>  if (switch_output_size(rec))
>>  trigger_hit(&switch_output_trigger);
>>  
>> @@ -1639,6 +1649,33 @@ static int parse_clockid(const struct option *opt, 
>> const char *str, int unset)
>>  return -1;
>>  }
>>  
>> +static int parse_output_max_size(const struct option *opt, const char *str,
>> + int unset)
>> +{
>> +unsigned long *s = (unsigned long *)opt->value;
>> +static struct parse_tag tags_size[] = {
>> +{ .tag  = 'B', .mult = 1   },
>> +{ .tag  = 'K', .mult = 1 << 10 },
>> +{ .tag  = 'M', .mult = 1 << 20 },
>> +{ .tag  = 'G', .mult = 1 << 30 },
>> +{ .tag  = 0 },
>> +};
>> +unsigned long val;
>> +
>> +if (unset) {
>> +*s = 0;
>> +return 0;
>> +}
>> +
>> +val = parse_tag_value(str, tags_size);
>> +if (val != (unsigned long) -1) {
>> +*s = val;
>> +return 0;
>> +}
>> +
>> +return -1;
>> +}
>> +
>>  static int record__parse_mmap_pages(const struct option *opt,
>>  const char *str,
>>  int unset __maybe_unused)
>> @@ -1946,6 +1983,8 @@ static struct option __record_options[] = {
>>   &nr_cblocks_default, "n", "Use  control blocks in 
>> asynchronous trace writing mode (default: 1, max: 4)",
>>   record__aio_parse),
>>  #endif
>> +OPT_CALLBACK(0, "output-max-size", &record.output_max_size,
>> + "size", "Output file maximum size", parse_output_max_size),
>>  OPT_END()
>>  };
>>  
>> -- 
>> 2.20.1
>>
> 


[PATCH v2] perf record: Add support for limit perf output file size

2019-02-21 Thread Jiwei Sun
The patch adds a new option to limit the output file size, then based
on it, we can create a wrapper of the perf command that uses the option
to avoid exhausting the disk space by the unconscious user.

Signed-off-by: Jiwei Sun 
---
v2 changes:
  - make patch based on latest Arnaldo's perf/core,
  - display warning message when reached the limit.
---
 tools/perf/builtin-record.c | 42 +
 1 file changed, 42 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 6c3719ac901d..dc3648c0816d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -83,6 +83,7 @@ struct record {
struct switch_outputswitch_output;
unsigned long long  samples;
cpu_set_t   affinity_mask;
+   unsigned long   output_max_size;/* = 0: unlimited */
 };
 
 static volatile int auxtrace_record__snapshot_started;
@@ -112,6 +113,12 @@ static bool switch_output_time(struct record *rec)
   trigger_is_ready(&switch_output_trigger);
 }
 
+static bool record__output_max_size_exceeded(struct record *rec)
+{
+   return (rec->output_max_size &&
+  rec->bytes_written >= rec->output_max_size);
+}
+
 static int record__write(struct record *rec, struct perf_mmap *map 
__maybe_unused,
 void *bf, size_t size)
 {
@@ -124,6 +131,12 @@ static int record__write(struct record *rec, struct 
perf_mmap *map __maybe_unuse
 
rec->bytes_written += size;
 
+   if (record__output_max_size_exceeded(rec)) {
+   pr_warning("WARNING: The perf data has already reached "
+  "the limit, stop recording!\n");
+   raise(SIGTERM);
+   }
+
if (switch_output_size(rec))
trigger_hit(&switch_output_trigger);
 
@@ -1671,6 +1684,33 @@ static int record__parse_affinity(const struct option 
*opt, const char *str, int
return 0;
 }
 
+static int parse_output_max_size(const struct option *opt,
+const char *str, int unset)
+{
+   unsigned long *s = (unsigned long *)opt->value;
+   static struct parse_tag tags_size[] = {
+   { .tag  = 'B', .mult = 1   },
+   { .tag  = 'K', .mult = 1 << 10 },
+   { .tag  = 'M', .mult = 1 << 20 },
+   { .tag  = 'G', .mult = 1 << 30 },
+   { .tag  = 0 },
+   };
+   unsigned long val;
+
+   if (unset) {
+   *s = 0;
+   return 0;
+   }
+
+   val = parse_tag_value(str, tags_size);
+   if (val != (unsigned long) -1) {
+   *s = val;
+   return 0;
+   }
+
+   return -1;
+}
+
 static int record__parse_mmap_pages(const struct option *opt,
const char *str,
int unset __maybe_unused)
@@ -1982,6 +2022,8 @@ static struct option __record_options[] = {
OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu",
 "Set affinity mask of trace reading thread to NUMA node 
cpu mask or cpu of processed mmap buffer",
 record__parse_affinity),
+   OPT_CALLBACK(0, "output-max-size", &record.output_max_size,
+"size", "Output file maximum size", parse_output_max_size),
OPT_END()
 };
 
-- 
2.20.1



Re: [PATCH v2] perf record: Add support for limit perf output file size

2019-02-24 Thread Jiwei Sun
Hi Arnaldo,

On 02/22/2019 10:53 PM, Arnaldo Carvalho de Melo wrote:
> Em Fri, Feb 22, 2019 at 03:19:04PM +0800, Jiwei Sun escreveu:
>> The patch adds a new option to limit the output file size, then based
>> on it, we can create a wrapper of the perf command that uses the option
>> to avoid exhausting the disk space by the unconscious user.
>>
>> Signed-off-by: Jiwei Sun 
>> ---
>> v2 changes:
> 
> Please do a v3 adding this new option to
> tools/perf/Documentation/perf-record.txt
> 
> Please also rename it to --max-size-output, because then we coudl use:
> 
> perf record --max-size-output
> 
> or:
> 
> perf record --max-size
> 
> or even:
> 
> perf record --max saving typing :-)
> 
> Also please show it in use, i.e. the output of it working.

Thanks for your advice, I will modify the patch and send a v3.

Thanks,
Regards,
Jiwei

> 
> 
> - Arnaldo
> 
>>   - make patch based on latest Arnaldo's perf/core,
>>   - display warning message when reached the limit.
>> ---
>>  tools/perf/builtin-record.c | 42 +
>>  1 file changed, 42 insertions(+)
>>
>> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
>> index 6c3719ac901d..dc3648c0816d 100644
>> --- a/tools/perf/builtin-record.c
>> +++ b/tools/perf/builtin-record.c
>> @@ -83,6 +83,7 @@ struct record {
>>  struct switch_outputswitch_output;
>>  unsigned long long  samples;
>>  cpu_set_t   affinity_mask;
>> +unsigned long   output_max_size;/* = 0: unlimited */
>>  };
>>  
>>  static volatile int auxtrace_record__snapshot_started;
>> @@ -112,6 +113,12 @@ static bool switch_output_time(struct record *rec)
>> trigger_is_ready(&switch_output_trigger);
>>  }
>>  
>> +static bool record__output_max_size_exceeded(struct record *rec)
>> +{
>> +return (rec->output_max_size &&
>> +   rec->bytes_written >= rec->output_max_size);
>> +}
>> +
>>  static int record__write(struct record *rec, struct perf_mmap *map 
>> __maybe_unused,
>>   void *bf, size_t size)
>>  {
>> @@ -124,6 +131,12 @@ static int record__write(struct record *rec, struct 
>> perf_mmap *map __maybe_unuse
>>  
>>  rec->bytes_written += size;
>>  
>> +if (record__output_max_size_exceeded(rec)) {
>> +pr_warning("WARNING: The perf data has already reached "
>> +   "the limit, stop recording!\n");
>> +raise(SIGTERM);
>> +}
>> +
>>  if (switch_output_size(rec))
>>  trigger_hit(&switch_output_trigger);
>>  
>> @@ -1671,6 +1684,33 @@ static int record__parse_affinity(const struct option 
>> *opt, const char *str, int
>>  return 0;
>>  }
>>  
>> +static int parse_output_max_size(const struct option *opt,
>> + const char *str, int unset)
>> +{
>> +unsigned long *s = (unsigned long *)opt->value;
>> +static struct parse_tag tags_size[] = {
>> +{ .tag  = 'B', .mult = 1   },
>> +{ .tag  = 'K', .mult = 1 << 10 },
>> +{ .tag  = 'M', .mult = 1 << 20 },
>> +{ .tag  = 'G', .mult = 1 << 30 },
>> +{ .tag  = 0 },
>> +};
>> +unsigned long val;
>> +
>> +if (unset) {
>> +*s = 0;
>> +return 0;
>> +}
>> +
>> +val = parse_tag_value(str, tags_size);
>> +if (val != (unsigned long) -1) {
>> +*s = val;
>> +return 0;
>> +}
>> +
>> +return -1;
>> +}
>> +
>>  static int record__parse_mmap_pages(const struct option *opt,
>>  const char *str,
>>  int unset __maybe_unused)
>> @@ -1982,6 +2022,8 @@ static struct option __record_options[] = {
>>  OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu",
>>   "Set affinity mask of trace reading thread to NUMA node 
>> cpu mask or cpu of processed mmap buffer",
>>   record__parse_affinity),
>> +OPT_CALLBACK(0, "output-max-size", &record.output_max_size,
>> + "size", "Output file maximum size", parse_output_max_size),
>>  OPT_END()
>>  };
>>  
>> -- 
>> 2.20.1
> 


[PATCH] rtc: adjust the next alarm expiring time to avoid a softlockups.

2018-04-16 Thread Jiwei Sun
cted stalls on CPUs/tasks:
[   29.934096]  2-: (20935 ticks this GP) idle=f4a/1/4611686018427387904 
softirq=754/754 fqs=4704
[   29.934096]  (detected by 3, t=21019 jiffies, g=55, c=54, q=42)
[   29.934096] Sending NMI from CPU 3 to CPUs 2:
[   29.948423] NMI backtrace for cpu 2
[   29.948423] CPU: 2 PID: 49 Comm: kworker/2:1 Not tainted 4.16.0 #5
[   29.948423] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 
Bochs 01/01/2011
[   29.952553] Workqueue: events rtc_timer_do_work
[   29.952553] RIP: 0010:__wake_up_common+0x0/0x120
[   29.952553] RSP: 0018:9db0801abcf0 EFLAGS: 0046
[   29.952553] RAX: 0292 RBX: 8dfb869feb88 RCX: 
[   29.952553] RDX: 0001 RSI: 0001 RDI: 8dfb869feb88
[   29.952553] RBP: 0001 R08:  R09: 9db0801abcf8
[   29.952553] R10: 0010 R11: 0001 R12: 0292
[   29.952553] R13: 0001 R14:  R15: 
[   29.952553] FS:  () GS:8dfb87d0() 
knlGS:
[   29.952553] CS:  0010 DS:  ES:  CR0: 80050033
[   29.952553] CR2: 7fff0ee7a9f0 CR3: 062b2000 CR4: 06e0
[   29.952553] DR0:  DR1:  DR2: 
[   29.952553] DR3:  DR6:  DR7: 
[   29.952553] Call Trace:
[   29.952553]  __wake_up_common_lock+0x65/0x90
[   29.952553]  rtc_handle_legacy_irq+0x91/0xb0
[   29.952553]  rtc_timer_do_work+0xcc/0x200
[   29.952553]  process_one_work+0x136/0x330
[   29.952553]  worker_thread+0x3f/0x3b0
[   29.952553]  kthread+0xf0/0x130
[   29.952553]  ? process_one_work+0x330/0x330
[   29.952553]  ? kthread_bind+0x10/0x10
[   29.952553]  ? call_usermodehelper_exec_async+0x10f/0x110
[   29.952553]  ret_from_fork+0x35/0x40
[   29.952553] Code: 90 90 90 90 90 90 90 90 90 90 90 48 8d 47 08 c7 07 00 00 
00 00 48 89 47 08 48 89 47 10 c3 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 <41> 57 
41 56 4d 89 c6 41 55 41 54 55 4c 89 cd 53 48 83 ec 10 4d
[   29.952553] INFO: NMI handler (nmi_cpu_backtrace_handler) took too long to 
run: 6.037 msecs

The root cause is as following.
When the hardware clock's time is modified later than the periodic
alarm clock's expire time, the rtc_timer_do_work's loop may spend
a long time to process.
In order to avoid the case, we can adjust the next expire time to
equating to "now + period".

Signed-off-by: Jiwei Sun 
---
 drivers/rtc/interface.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 672b192..d76eceb 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -877,6 +877,9 @@ void rtc_timer_do_work(struct work_struct *work)
 
/* Re-add/fwd periodic timers */
if (ktime_to_ns(timer->period)) {
+   if (now - next->expires > timer->period)
+   timer->node.expires = now;
+
timer->node.expires = ktime_add(timer->node.expires,
timer->period);
timer->enabled = 1;
-- 
1.9.1



Re: [PATCH] MIPS: reset all task's asid to 0 after asid_cache(cpu) overflows

2017-03-07 Thread Jiwei Sun


On 03/06/2017 04:34 PM, Sergei Shtylyov wrote:
> On 3/6/2017 10:21 AM, jsun4 wrote:
> 
>>>> If asid_cache(cpu) overflows, there may be two tasks with the same
>>>> asid. It is a risk that the two different tasks may have the same
>>>> address space.
>>>>
>>>> A process will update its asid to newer version only when switch_mm()
>>>> is called and matches the following condition:
>>>> if ((cpu_context(cpu, next) ^ asid_cache(cpu))
>>>> & asid_version_mask(cpu))
>>>> get_new_mmu_context(next, cpu);
>>>> If asid_cache(cpu) overflows, cpu_context(cpu,next) and asid_cache(cpu)
>>>> will be reset to asid_first_version(cpu), and start a new cycle. It
>>>> can result in two tasks that have the same ASID in the process list.
>>>>
>>>> For example, in CONFIG_CPU_MIPS32_R2, task named A's asid on CPU1 is
>>>> 0x100, and has been sleeping and been not scheduled. After a long period
>>>> of time, another running task named B's asid on CPU1 is 0x, and
>>>> asid cached in the CPU1 is 0x too, next task named C is forked,
>>>> when schedule from B to C on CPU1, asid_cache(cpu) will overflow, so C's
>>>> asid on CPU1 will be 0x100 according to get_new_mmu_context(). A's asid
>>>> is the same as C, if now A is rescheduled on CPU1, A's asid is not able
>>>> to renew according to 'if' clause, and the local TLB entry can't be
>>>> flushed too, A's address space will be the same as C.
>>>>
>>>> If asid_cache(cpu) overflows, all of user space task's asid on this CPU
>>>> are able to set a invalid value (such as 0), it will avoid the risk.
>>>>
>>>> Signed-off-by: Jiwei Sun 
>>>> ---
>>>>  arch/mips/include/asm/mmu_context.h | 9 -
>>>>  1 file changed, 8 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/arch/mips/include/asm/mmu_context.h 
>>>> b/arch/mips/include/asm/mmu_context.h
>>>> index ddd57ad..1f60efc 100644
>>>> --- a/arch/mips/include/asm/mmu_context.h
>>>> +++ b/arch/mips/include/asm/mmu_context.h
>>>> @@ -108,8 +108,15 @@ static inline void enter_lazy_tlb(struct mm_struct 
>>>> *mm, struct task_struct *tsk)
>>>>  #else
>>>>  local_flush_tlb_all();/* start new asid cycle */
>>>>  #endif
>>>> -if (!asid)/* fix version if needed */
>>>> +if (!asid) {/* fix version if needed */
>>>> +struct task_struct *p;
>>>> +
>>>> +for_each_process(p) {
>>>> +if ((p->mm))
>>>
>>>Why double parens?
>>
>> At the beginning, the code was written as following
>> if ((p->mm) && (p->mm != mm))
>> cpu_context(cpu, p->mm) = 0;
>>
>> Because cpu_context(cpu,mm) will be changed to asid_first_version(cpu) after 
>> 'for' loop,
>> and in order to improve the efficiency of the loop, I deleted "&& (p->mm != 
>> mm)",
>> but I forgot to delete the redundant parentheses.
> 
>Note that parens around 'p->mm' were never needed. And neither around the 
> right operand of &&.

You are right, I will pay attention to similar problems next time.
Thanks for your reminder.

Best regards,
Jiwei

> 
>> Thanks,
>> Best regards,
>> Jiwei
> 
> MBR, Sergei
> 


[PATCH] MIPS: reset all task's asid to 0 after asid_cache(cpu) overflows

2017-03-04 Thread Jiwei Sun
If asid_cache(cpu) overflows, there may be two tasks with the same
asid. It is a risk that the two different tasks may have the same
address space.

A process will update its asid to newer version only when switch_mm()
is called and matches the following condition:
if ((cpu_context(cpu, next) ^ asid_cache(cpu))
& asid_version_mask(cpu))
get_new_mmu_context(next, cpu);
If asid_cache(cpu) overflows, cpu_context(cpu,next) and asid_cache(cpu)
will be reset to asid_first_version(cpu), and start a new cycle. It
can result in two tasks that have the same ASID in the process list.

For example, in CONFIG_CPU_MIPS32_R2, task named A's asid on CPU1 is
0x100, and has been sleeping and been not scheduled. After a long period
of time, another running task named B's asid on CPU1 is 0x, and
asid cached in the CPU1 is 0x too, next task named C is forked,
when schedule from B to C on CPU1, asid_cache(cpu) will overflow, so C's
asid on CPU1 will be 0x100 according to get_new_mmu_context(). A's asid
is the same as C, if now A is rescheduled on CPU1, A's asid is not able
to renew according to 'if' clause, and the local TLB entry can't be
flushed too, A's address space will be the same as C.

If asid_cache(cpu) overflows, all of user space task's asid on this CPU
are able to set a invalid value (such as 0), it will avoid the risk.

Signed-off-by: Jiwei Sun 
---
 arch/mips/include/asm/mmu_context.h | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/mmu_context.h 
b/arch/mips/include/asm/mmu_context.h
index ddd57ad..1f60efc 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -108,8 +108,15 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, 
struct task_struct *tsk)
 #else
local_flush_tlb_all();  /* start new asid cycle */
 #endif
-   if (!asid)  /* fix version if needed */
+   if (!asid) {/* fix version if needed */
+   struct task_struct *p;
+
+   for_each_process(p) {
+   if ((p->mm))
+   cpu_context(cpu, p->mm) = 0;
+   }
asid = asid_first_version(cpu);
+   }
}
 
cpu_context(cpu, mm) = asid_cache(cpu) = asid;
-- 
1.9.1