1 /* Reduced and adapted from Linux: fs/proc/inode.c: proc_reg_open
4 /* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
8 typedef unsigned char u8
;
12 typedef unsigned int gfp_t
;
16 struct proc_dir_entry
;
18 struct inode
{ /* [...snip...] */ };
21 PROC_ENTRY_PERMANENT
= 1U << 0,
26 int (*proc_open
)(struct inode
*, struct file
*);
28 int (*proc_release
)(struct inode
*, struct file
*);
32 struct proc_dir_entry
{
34 struct completion
*pde_unload_completion
;
37 const struct proc_ops
*proc_ops
;
38 const struct file_operations
*proc_dir_ops
;
53 struct proc_dir_entry
*pde
;
55 struct inode vfs_inode
;
60 static struct kmem_cache
*pde_opener_cache
__attribute__((__section__(".data..ro_after_init")));
64 void *kmem_cache_alloc(struct kmem_cache
*, gfp_t flags
) __attribute__((__malloc__
));
65 void kmem_cache_free(struct kmem_cache
*, void *);
67 static inline bool pde_is_permanent(const struct proc_dir_entry
*pde
)
69 return pde
->flags
& PROC_ENTRY_PERMANENT
;
72 static inline struct proc_inode
*PROC_I(const struct inode
*inode
)
74 char *__mptr
= (char *)(inode
);
75 return ((struct proc_inode
*)(__mptr
- __builtin_offsetof(struct proc_inode
, vfs_inode
)));
78 static inline struct proc_dir_entry
*PDE(const struct inode
*inode
)
80 return PROC_I(inode
)->pde
;
83 /* We don't want to emit bogus use of uninitialized value 'pdeo'
84 warnings from -Wanalyzer-use-of-uninitialized-value in this function;
85 these would require following infeasible paths in which "release" is
86 first NULL (to avoid the initialization of "pdeo") and then is non-NULL
89 "release" is sufficiently complicated in this function to hit the
90 complexity limit for symbolic values during enode exploration. */
92 static int proc_reg_open(struct inode
*inode
, struct file
*file
)
94 struct proc_dir_entry
*pde
= PDE(inode
);
98 int (*open
)(struct inode
*, struct file
*);
99 int (*release
)(struct inode
*, struct file
*);
101 struct pde_opener
*pdeo
;
103 if (pde_is_permanent(pde
)) {
104 open
= pde
->proc_ops
->proc_open
;
106 rv
= open(inode
, file
);
112 release
= pde
->proc_ops
->proc_release
;
114 pdeo
= (struct pde_opener
*) kmem_cache_alloc(pde_opener_cache
,
115 ((( gfp_t
)(0x400u
|0x800u
))
124 open
= pde
->proc_ops
->proc_open
;
126 rv
= open(inode
, file
);
131 pdeo
->file
= file
; /* { dg-bogus "uninit" } */
134 kmem_cache_free(pde_opener_cache
, pdeo
); /* { dg-bogus "uninit" } */