Skip to content

Commit ecc4d6a

Browse files
committed
Merge branch 'slab/for-6.12/kmem_cache_args' into slab/for-next
Merge kmem_cache_create() refactoring by Christian Brauner. Note this includes a merge of the vfs.file tree that contains the prerequisity kmem_cache_create_rcu() work.
2 parents a715e94 + 4b7ff9a commit ecc4d6a

File tree

16 files changed

+548
-284
lines changed

16 files changed

+548
-284
lines changed

drivers/net/tun.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3451,6 +3451,12 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
34513451
struct tun_file *tfile = file->private_data;
34523452
int ret;
34533453

3454+
if (on) {
3455+
ret = file_f_owner_allocate(file);
3456+
if (ret)
3457+
goto out;
3458+
}
3459+
34543460
if ((ret = fasync_helper(fd, file, on, &tfile->fasync)) < 0)
34553461
goto out;
34563462

drivers/tty/tty_io.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2225,6 +2225,12 @@ static int __tty_fasync(int fd, struct file *filp, int on)
22252225
if (tty_paranoia_check(tty, file_inode(filp), "tty_fasync"))
22262226
goto out;
22272227

2228+
if (on) {
2229+
retval = file_f_owner_allocate(filp);
2230+
if (retval)
2231+
goto out;
2232+
}
2233+
22282234
retval = fasync_helper(fd, filp, on, &tty->fasync);
22292235
if (retval <= 0)
22302236
goto out;

fs/fcntl.c

Lines changed: 132 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include <asm/siginfo.h>
3434
#include <linux/uaccess.h>
3535

36+
#include "internal.h"
37+
3638
#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
3739

3840
static int setfl(int fd, struct file * filp, unsigned int arg)
@@ -87,22 +89,64 @@ static int setfl(int fd, struct file * filp, unsigned int arg)
8789
return error;
8890
}
8991

92+
/*
93+
* Allocate an file->f_owner struct if it doesn't exist, handling racing
94+
* allocations correctly.
95+
*/
96+
int file_f_owner_allocate(struct file *file)
97+
{
98+
struct fown_struct *f_owner;
99+
100+
f_owner = file_f_owner(file);
101+
if (f_owner)
102+
return 0;
103+
104+
f_owner = kzalloc(sizeof(struct fown_struct), GFP_KERNEL);
105+
if (!f_owner)
106+
return -ENOMEM;
107+
108+
rwlock_init(&f_owner->lock);
109+
f_owner->file = file;
110+
/* If someone else raced us, drop our allocation. */
111+
if (unlikely(cmpxchg(&file->f_owner, NULL, f_owner)))
112+
kfree(f_owner);
113+
return 0;
114+
}
115+
EXPORT_SYMBOL(file_f_owner_allocate);
116+
117+
void file_f_owner_release(struct file *file)
118+
{
119+
struct fown_struct *f_owner;
120+
121+
f_owner = file_f_owner(file);
122+
if (f_owner) {
123+
put_pid(f_owner->pid);
124+
kfree(f_owner);
125+
}
126+
}
127+
90128
static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
91129
int force)
92130
{
93-
write_lock_irq(&filp->f_owner.lock);
94-
if (force || !filp->f_owner.pid) {
95-
put_pid(filp->f_owner.pid);
96-
filp->f_owner.pid = get_pid(pid);
97-
filp->f_owner.pid_type = type;
131+
struct fown_struct *f_owner;
132+
133+
f_owner = file_f_owner(filp);
134+
if (WARN_ON_ONCE(!f_owner))
135+
return;
136+
137+
write_lock_irq(&f_owner->lock);
138+
if (force || !f_owner->pid) {
139+
put_pid(f_owner->pid);
140+
f_owner->pid = get_pid(pid);
141+
f_owner->pid_type = type;
98142

99143
if (pid) {
100144
const struct cred *cred = current_cred();
101-
filp->f_owner.uid = cred->uid;
102-
filp->f_owner.euid = cred->euid;
145+
f_owner->uid = cred->uid;
146+
f_owner->euid = cred->euid;
103147
}
104148
}
105-
write_unlock_irq(&filp->f_owner.lock);
149+
write_unlock_irq(&f_owner->lock);
106150
}
107151

108152
void __f_setown(struct file *filp, struct pid *pid, enum pid_type type,
@@ -119,6 +163,8 @@ int f_setown(struct file *filp, int who, int force)
119163
struct pid *pid = NULL;
120164
int ret = 0;
121165

166+
might_sleep();
167+
122168
type = PIDTYPE_TGID;
123169
if (who < 0) {
124170
/* avoid overflow below */
@@ -129,6 +175,10 @@ int f_setown(struct file *filp, int who, int force)
129175
who = -who;
130176
}
131177

178+
ret = file_f_owner_allocate(filp);
179+
if (ret)
180+
return ret;
181+
132182
rcu_read_lock();
133183
if (who) {
134184
pid = find_vpid(who);
@@ -152,16 +202,21 @@ void f_delown(struct file *filp)
152202
pid_t f_getown(struct file *filp)
153203
{
154204
pid_t pid = 0;
205+
struct fown_struct *f_owner;
206+
207+
f_owner = file_f_owner(filp);
208+
if (!f_owner)
209+
return pid;
155210

156-
read_lock_irq(&filp->f_owner.lock);
211+
read_lock_irq(&f_owner->lock);
157212
rcu_read_lock();
158-
if (pid_task(filp->f_owner.pid, filp->f_owner.pid_type)) {
159-
pid = pid_vnr(filp->f_owner.pid);
160-
if (filp->f_owner.pid_type == PIDTYPE_PGID)
213+
if (pid_task(f_owner->pid, f_owner->pid_type)) {
214+
pid = pid_vnr(f_owner->pid);
215+
if (f_owner->pid_type == PIDTYPE_PGID)
161216
pid = -pid;
162217
}
163218
rcu_read_unlock();
164-
read_unlock_irq(&filp->f_owner.lock);
219+
read_unlock_irq(&f_owner->lock);
165220
return pid;
166221
}
167222

@@ -194,6 +249,10 @@ static int f_setown_ex(struct file *filp, unsigned long arg)
194249
return -EINVAL;
195250
}
196251

252+
ret = file_f_owner_allocate(filp);
253+
if (ret)
254+
return ret;
255+
197256
rcu_read_lock();
198257
pid = find_vpid(owner.pid);
199258
if (owner.pid && !pid)
@@ -210,13 +269,20 @@ static int f_getown_ex(struct file *filp, unsigned long arg)
210269
struct f_owner_ex __user *owner_p = (void __user *)arg;
211270
struct f_owner_ex owner = {};
212271
int ret = 0;
272+
struct fown_struct *f_owner;
273+
enum pid_type pid_type = PIDTYPE_PID;
213274

214-
read_lock_irq(&filp->f_owner.lock);
215-
rcu_read_lock();
216-
if (pid_task(filp->f_owner.pid, filp->f_owner.pid_type))
217-
owner.pid = pid_vnr(filp->f_owner.pid);
218-
rcu_read_unlock();
219-
switch (filp->f_owner.pid_type) {
275+
f_owner = file_f_owner(filp);
276+
if (f_owner) {
277+
read_lock_irq(&f_owner->lock);
278+
rcu_read_lock();
279+
if (pid_task(f_owner->pid, f_owner->pid_type))
280+
owner.pid = pid_vnr(f_owner->pid);
281+
rcu_read_unlock();
282+
pid_type = f_owner->pid_type;
283+
}
284+
285+
switch (pid_type) {
220286
case PIDTYPE_PID:
221287
owner.type = F_OWNER_TID;
222288
break;
@@ -234,7 +300,8 @@ static int f_getown_ex(struct file *filp, unsigned long arg)
234300
ret = -EINVAL;
235301
break;
236302
}
237-
read_unlock_irq(&filp->f_owner.lock);
303+
if (f_owner)
304+
read_unlock_irq(&f_owner->lock);
238305

239306
if (!ret) {
240307
ret = copy_to_user(owner_p, &owner, sizeof(owner));
@@ -248,14 +315,18 @@ static int f_getown_ex(struct file *filp, unsigned long arg)
248315
static int f_getowner_uids(struct file *filp, unsigned long arg)
249316
{
250317
struct user_namespace *user_ns = current_user_ns();
318+
struct fown_struct *f_owner;
251319
uid_t __user *dst = (void __user *)arg;
252-
uid_t src[2];
320+
uid_t src[2] = {0, 0};
253321
int err;
254322

255-
read_lock_irq(&filp->f_owner.lock);
256-
src[0] = from_kuid(user_ns, filp->f_owner.uid);
257-
src[1] = from_kuid(user_ns, filp->f_owner.euid);
258-
read_unlock_irq(&filp->f_owner.lock);
323+
f_owner = file_f_owner(filp);
324+
if (f_owner) {
325+
read_lock_irq(&f_owner->lock);
326+
src[0] = from_kuid(user_ns, f_owner->uid);
327+
src[1] = from_kuid(user_ns, f_owner->euid);
328+
read_unlock_irq(&f_owner->lock);
329+
}
259330

260331
err = put_user(src[0], &dst[0]);
261332
err |= put_user(src[1], &dst[1]);
@@ -343,6 +414,30 @@ static long f_dupfd_query(int fd, struct file *filp)
343414
return f.file == filp;
344415
}
345416

417+
static int f_owner_sig(struct file *filp, int signum, bool setsig)
418+
{
419+
int ret = 0;
420+
struct fown_struct *f_owner;
421+
422+
might_sleep();
423+
424+
if (setsig) {
425+
if (!valid_signal(signum))
426+
return -EINVAL;
427+
428+
ret = file_f_owner_allocate(filp);
429+
if (ret)
430+
return ret;
431+
}
432+
433+
f_owner = file_f_owner(filp);
434+
if (setsig)
435+
f_owner->signum = signum;
436+
else if (f_owner)
437+
ret = f_owner->signum;
438+
return ret;
439+
}
440+
346441
static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
347442
struct file *filp)
348443
{
@@ -421,15 +516,10 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
421516
err = f_getowner_uids(filp, arg);
422517
break;
423518
case F_GETSIG:
424-
err = filp->f_owner.signum;
519+
err = f_owner_sig(filp, 0, false);
425520
break;
426521
case F_SETSIG:
427-
/* arg == 0 restores default behaviour. */
428-
if (!valid_signal(argi)) {
429-
break;
430-
}
431-
err = 0;
432-
filp->f_owner.signum = argi;
522+
err = f_owner_sig(filp, argi, true);
433523
break;
434524
case F_GETLEASE:
435525
err = fcntl_getlease(filp);
@@ -844,14 +934,19 @@ static void send_sigurg_to_task(struct task_struct *p,
844934
do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, type);
845935
}
846936

847-
int send_sigurg(struct fown_struct *fown)
937+
int send_sigurg(struct file *file)
848938
{
939+
struct fown_struct *fown;
849940
struct task_struct *p;
850941
enum pid_type type;
851942
struct pid *pid;
852943
unsigned long flags;
853944
int ret = 0;
854945

946+
fown = file_f_owner(file);
947+
if (!fown)
948+
return 0;
949+
855950
read_lock_irqsave(&fown->lock, flags);
856951

857952
type = fown->pid_type;
@@ -1027,13 +1122,16 @@ static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band)
10271122
}
10281123
read_lock_irqsave(&fa->fa_lock, flags);
10291124
if (fa->fa_file) {
1030-
fown = &fa->fa_file->f_owner;
1125+
fown = file_f_owner(fa->fa_file);
1126+
if (!fown)
1127+
goto next;
10311128
/* Don't send SIGURG to processes which have not set a
10321129
queued signum: SIGURG has its own default signalling
10331130
mechanism. */
10341131
if (!(sig == SIGURG && fown->signum == 0))
10351132
send_sigio(fown, fa->fa_fd, band);
10361133
}
1134+
next:
10371135
read_unlock_irqrestore(&fa->fa_lock, flags);
10381136
fa = rcu_dereference(fa->fa_next);
10391137
}

fs/file_table.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ static int init_file(struct file *f, int flags, const struct cred *cred)
155155
return error;
156156
}
157157

158-
rwlock_init(&f->f_owner.lock);
159158
spin_lock_init(&f->f_lock);
160159
mutex_init(&f->f_pos_lock);
161160
f->f_flags = flags;
@@ -425,7 +424,7 @@ static void __fput(struct file *file)
425424
cdev_put(inode->i_cdev);
426425
}
427426
fops_put(file->f_op);
428-
put_pid(file->f_owner.pid);
427+
file_f_owner_release(file);
429428
put_file_access(file);
430429
dput(dentry);
431430
if (unlikely(mode & FMODE_NEED_UNMOUNT))
@@ -512,9 +511,14 @@ EXPORT_SYMBOL(__fput_sync);
512511

513512
void __init files_init(void)
514513
{
515-
filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
516-
SLAB_TYPESAFE_BY_RCU | SLAB_HWCACHE_ALIGN |
517-
SLAB_PANIC | SLAB_ACCOUNT, NULL);
514+
struct kmem_cache_args args = {
515+
.use_freeptr_offset = true,
516+
.freeptr_offset = offsetof(struct file, f_freeptr),
517+
};
518+
519+
filp_cachep = kmem_cache_create("filp", sizeof(struct file), &args,
520+
SLAB_HWCACHE_ALIGN | SLAB_PANIC |
521+
SLAB_ACCOUNT | SLAB_TYPESAFE_BY_RCU);
518522
percpu_counter_init(&nr_files, 0, GFP_KERNEL);
519523
}
520524

fs/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,3 +337,4 @@ static inline bool path_mounted(const struct path *path)
337337
{
338338
return path->mnt->mnt_root == path->dentry;
339339
}
340+
void file_f_owner_release(struct file *file);

fs/locks.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1451,7 +1451,7 @@ int lease_modify(struct file_lease *fl, int arg, struct list_head *dispose)
14511451
struct file *filp = fl->c.flc_file;
14521452

14531453
f_delown(filp);
1454-
filp->f_owner.signum = 0;
1454+
file_f_owner(filp)->signum = 0;
14551455
fasync_helper(0, fl->c.flc_file, 0, &fl->fl_fasync);
14561456
if (fl->fl_fasync != NULL) {
14571457
printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync);
@@ -1783,6 +1783,10 @@ generic_add_lease(struct file *filp, int arg, struct file_lease **flp, void **pr
17831783
lease = *flp;
17841784
trace_generic_add_lease(inode, lease);
17851785

1786+
error = file_f_owner_allocate(filp);
1787+
if (error)
1788+
return error;
1789+
17861790
/* Note that arg is never F_UNLCK here */
17871791
ctx = locks_get_lock_context(inode, arg);
17881792
if (!ctx)

fs/notify/dnotify/dnotify.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
110110
prev = &dn->dn_next;
111111
continue;
112112
}
113-
fown = &dn->dn_filp->f_owner;
113+
fown = file_f_owner(dn->dn_filp);
114114
send_sigio(fown, dn->dn_fd, POLL_MSG);
115115
if (dn->dn_mask & FS_DN_MULTISHOT)
116116
prev = &dn->dn_next;
@@ -316,6 +316,10 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned int arg)
316316
goto out_err;
317317
}
318318

319+
error = file_f_owner_allocate(filp);
320+
if (error)
321+
goto out_err;
322+
319323
/* set up the new_fsn_mark and new_dn_mark */
320324
new_fsn_mark = &new_dn_mark->fsn_mark;
321325
fsnotify_init_mark(new_fsn_mark, dnotify_group);

0 commit comments

Comments
 (0)