@@ -103,48 +103,50 @@ struct bsd_acct_struct {
103
103
atomic_long_t count ;
104
104
struct rcu_head rcu ;
105
105
struct mutex lock ;
106
- int active ;
106
+ bool active ;
107
+ bool check_space ;
107
108
unsigned long needcheck ;
108
109
struct file * file ;
109
110
struct pid_namespace * ns ;
110
111
struct work_struct work ;
111
112
struct completion done ;
113
+ acct_t ac ;
112
114
};
113
115
114
- static void do_acct_process (struct bsd_acct_struct * acct );
116
+ static void fill_ac (struct bsd_acct_struct * acct );
117
+ static void acct_write_process (struct bsd_acct_struct * acct );
115
118
116
119
/*
117
120
* Check the amount of free space and suspend/resume accordingly.
118
121
*/
119
- static int check_free_space (struct bsd_acct_struct * acct )
122
+ static bool check_free_space (struct bsd_acct_struct * acct )
120
123
{
121
124
struct kstatfs sbuf ;
122
125
123
- if (time_is_after_jiffies ( acct -> needcheck ) )
124
- goto out ;
126
+ if (! acct -> check_space )
127
+ return acct -> active ;
125
128
126
129
/* May block */
127
130
if (vfs_statfs (& acct -> file -> f_path , & sbuf ))
128
- goto out ;
131
+ return acct -> active ;
129
132
130
133
if (acct -> active ) {
131
134
u64 suspend = sbuf .f_blocks * SUSPEND ;
132
135
do_div (suspend , 100 );
133
136
if (sbuf .f_bavail <= suspend ) {
134
- acct -> active = 0 ;
137
+ acct -> active = false ;
135
138
pr_info ("Process accounting paused\n" );
136
139
}
137
140
} else {
138
141
u64 resume = sbuf .f_blocks * RESUME ;
139
142
do_div (resume , 100 );
140
143
if (sbuf .f_bavail >= resume ) {
141
- acct -> active = 1 ;
144
+ acct -> active = true ;
142
145
pr_info ("Process accounting resumed\n" );
143
146
}
144
147
}
145
148
146
149
acct -> needcheck = jiffies + ACCT_TIMEOUT * HZ ;
147
- out :
148
150
return acct -> active ;
149
151
}
150
152
@@ -189,7 +191,11 @@ static void acct_pin_kill(struct fs_pin *pin)
189
191
{
190
192
struct bsd_acct_struct * acct = to_acct (pin );
191
193
mutex_lock (& acct -> lock );
192
- do_acct_process (acct );
194
+ /*
195
+ * Fill the accounting struct with the exiting task's info
196
+ * before punting to the workqueue.
197
+ */
198
+ fill_ac (acct );
193
199
schedule_work (& acct -> work );
194
200
wait_for_completion (& acct -> done );
195
201
cmpxchg (& acct -> ns -> bacct , pin , NULL );
@@ -202,6 +208,9 @@ static void close_work(struct work_struct *work)
202
208
{
203
209
struct bsd_acct_struct * acct = container_of (work , struct bsd_acct_struct , work );
204
210
struct file * file = acct -> file ;
211
+
212
+ /* We were fired by acct_pin_kill() which holds acct->lock. */
213
+ acct_write_process (acct );
205
214
if (file -> f_op -> flush )
206
215
file -> f_op -> flush (file , NULL );
207
216
__fput_sync (file );
@@ -430,13 +439,27 @@ static u32 encode_float(u64 value)
430
439
* do_exit() or when switching to a different output file.
431
440
*/
432
441
433
- static void fill_ac (acct_t * ac )
442
+ static void fill_ac (struct bsd_acct_struct * acct )
434
443
{
435
444
struct pacct_struct * pacct = & current -> signal -> pacct ;
445
+ struct file * file = acct -> file ;
446
+ acct_t * ac = & acct -> ac ;
436
447
u64 elapsed , run_time ;
437
448
time64_t btime ;
438
449
struct tty_struct * tty ;
439
450
451
+ lockdep_assert_held (& acct -> lock );
452
+
453
+ if (time_is_after_jiffies (acct -> needcheck )) {
454
+ acct -> check_space = false;
455
+
456
+ /* Don't fill in @ac if nothing will be written. */
457
+ if (!acct -> active )
458
+ return ;
459
+ } else {
460
+ acct -> check_space = true;
461
+ }
462
+
440
463
/*
441
464
* Fill the accounting struct with the needed info as recorded
442
465
* by the different kernel functions.
@@ -484,64 +507,61 @@ static void fill_ac(acct_t *ac)
484
507
ac -> ac_majflt = encode_comp_t (pacct -> ac_majflt );
485
508
ac -> ac_exitcode = pacct -> ac_exitcode ;
486
509
spin_unlock_irq (& current -> sighand -> siglock );
487
- }
488
- /*
489
- * do_acct_process does all actual work. Caller holds the reference to file.
490
- */
491
- static void do_acct_process (struct bsd_acct_struct * acct )
492
- {
493
- acct_t ac ;
494
- unsigned long flim ;
495
- const struct cred * orig_cred ;
496
- struct file * file = acct -> file ;
497
-
498
- /*
499
- * Accounting records are not subject to resource limits.
500
- */
501
- flim = rlimit (RLIMIT_FSIZE );
502
- current -> signal -> rlim [RLIMIT_FSIZE ].rlim_cur = RLIM_INFINITY ;
503
- /* Perform file operations on behalf of whoever enabled accounting */
504
- orig_cred = override_creds (file -> f_cred );
505
510
506
- /*
507
- * First check to see if there is enough free_space to continue
508
- * the process accounting system.
509
- */
510
- if (!check_free_space (acct ))
511
- goto out ;
512
-
513
- fill_ac (& ac );
514
511
/* we really need to bite the bullet and change layout */
515
- ac . ac_uid = from_kuid_munged (file -> f_cred -> user_ns , orig_cred -> uid );
516
- ac . ac_gid = from_kgid_munged (file -> f_cred -> user_ns , orig_cred -> gid );
512
+ ac -> ac_uid = from_kuid_munged (file -> f_cred -> user_ns , current_uid () );
513
+ ac -> ac_gid = from_kgid_munged (file -> f_cred -> user_ns , current_gid () );
517
514
#if ACCT_VERSION == 1 || ACCT_VERSION == 2
518
515
/* backward-compatible 16 bit fields */
519
- ac . ac_uid16 = ac . ac_uid ;
520
- ac . ac_gid16 = ac . ac_gid ;
516
+ ac -> ac_uid16 = ac -> ac_uid ;
517
+ ac -> ac_gid16 = ac -> ac_gid ;
521
518
#elif ACCT_VERSION == 3
522
519
{
523
520
struct pid_namespace * ns = acct -> ns ;
524
521
525
- ac . ac_pid = task_tgid_nr_ns (current , ns );
522
+ ac -> ac_pid = task_tgid_nr_ns (current , ns );
526
523
rcu_read_lock ();
527
- ac .ac_ppid = task_tgid_nr_ns (rcu_dereference (current -> real_parent ),
528
- ns );
524
+ ac -> ac_ppid = task_tgid_nr_ns (rcu_dereference (current -> real_parent ), ns );
529
525
rcu_read_unlock ();
530
526
}
531
527
#endif
528
+ }
529
+
530
+ static void acct_write_process (struct bsd_acct_struct * acct )
531
+ {
532
+ struct file * file = acct -> file ;
533
+ const struct cred * cred ;
534
+ acct_t * ac = & acct -> ac ;
535
+
536
+ /* Perform file operations on behalf of whoever enabled accounting */
537
+ cred = override_creds (file -> f_cred );
538
+
532
539
/*
533
- * Get freeze protection. If the fs is frozen, just skip the write
534
- * as we could deadlock the system otherwise.
540
+ * First check to see if there is enough free_space to continue
541
+ * the process accounting system. Then get freeze protection. If
542
+ * the fs is frozen, just skip the write as we could deadlock
543
+ * the system otherwise.
535
544
*/
536
- if (file_start_write_trylock (file )) {
545
+ if (check_free_space ( acct ) && file_start_write_trylock (file )) {
537
546
/* it's been opened O_APPEND, so position is irrelevant */
538
547
loff_t pos = 0 ;
539
- __kernel_write (file , & ac , sizeof (acct_t ), & pos );
548
+ __kernel_write (file , ac , sizeof (acct_t ), & pos );
540
549
file_end_write (file );
541
550
}
542
- out :
551
+
552
+ revert_creds (cred );
553
+ }
554
+
555
+ static void do_acct_process (struct bsd_acct_struct * acct )
556
+ {
557
+ unsigned long flim ;
558
+
559
+ /* Accounting records are not subject to resource limits. */
560
+ flim = rlimit (RLIMIT_FSIZE );
561
+ current -> signal -> rlim [RLIMIT_FSIZE ].rlim_cur = RLIM_INFINITY ;
562
+ fill_ac (acct );
563
+ acct_write_process (acct );
543
564
current -> signal -> rlim [RLIMIT_FSIZE ].rlim_cur = flim ;
544
- revert_creds (orig_cred );
545
565
}
546
566
547
567
/**
0 commit comments