10
10
#include <linux/mm.h>
11
11
#include <linux/string.h>
12
12
#include <linux/stat.h>
13
+ #include <linux/completion.h>
13
14
#include <linux/file.h>
14
15
#include <linux/limits.h>
15
16
#include <linux/init.h>
@@ -140,6 +141,251 @@ static const struct super_operations proc_sops = {
140
141
.remount_fs = proc_remount ,
141
142
};
142
143
144
+ static void pde_users_dec (struct proc_dir_entry * pde )
145
+ {
146
+ spin_lock (& pde -> pde_unload_lock );
147
+ pde -> pde_users -- ;
148
+ if (pde -> pde_unload_completion && pde -> pde_users == 0 )
149
+ complete (pde -> pde_unload_completion );
150
+ spin_unlock (& pde -> pde_unload_lock );
151
+ }
152
+
153
+ static loff_t proc_reg_llseek (struct file * file , loff_t offset , int whence )
154
+ {
155
+ struct proc_dir_entry * pde = PDE (file -> f_path .dentry -> d_inode );
156
+ loff_t rv = - EINVAL ;
157
+ loff_t (* llseek )(struct file * , loff_t , int );
158
+
159
+ spin_lock (& pde -> pde_unload_lock );
160
+ /*
161
+ * remove_proc_entry() is going to delete PDE (as part of module
162
+ * cleanup sequence). No new callers into module allowed.
163
+ */
164
+ if (!pde -> proc_fops ) {
165
+ spin_unlock (& pde -> pde_unload_lock );
166
+ return rv ;
167
+ }
168
+ /*
169
+ * Bump refcount so that remove_proc_entry will wail for ->llseek to
170
+ * complete.
171
+ */
172
+ pde -> pde_users ++ ;
173
+ /*
174
+ * Save function pointer under lock, to protect against ->proc_fops
175
+ * NULL'ifying right after ->pde_unload_lock is dropped.
176
+ */
177
+ llseek = pde -> proc_fops -> llseek ;
178
+ spin_unlock (& pde -> pde_unload_lock );
179
+
180
+ if (!llseek )
181
+ llseek = default_llseek ;
182
+ rv = llseek (file , offset , whence );
183
+
184
+ pde_users_dec (pde );
185
+ return rv ;
186
+ }
187
+
188
+ static ssize_t proc_reg_read (struct file * file , char __user * buf , size_t count , loff_t * ppos )
189
+ {
190
+ struct proc_dir_entry * pde = PDE (file -> f_path .dentry -> d_inode );
191
+ ssize_t rv = - EIO ;
192
+ ssize_t (* read )(struct file * , char __user * , size_t , loff_t * );
193
+
194
+ spin_lock (& pde -> pde_unload_lock );
195
+ if (!pde -> proc_fops ) {
196
+ spin_unlock (& pde -> pde_unload_lock );
197
+ return rv ;
198
+ }
199
+ pde -> pde_users ++ ;
200
+ read = pde -> proc_fops -> read ;
201
+ spin_unlock (& pde -> pde_unload_lock );
202
+
203
+ if (read )
204
+ rv = read (file , buf , count , ppos );
205
+
206
+ pde_users_dec (pde );
207
+ return rv ;
208
+ }
209
+
210
+ static ssize_t proc_reg_write (struct file * file , const char __user * buf , size_t count , loff_t * ppos )
211
+ {
212
+ struct proc_dir_entry * pde = PDE (file -> f_path .dentry -> d_inode );
213
+ ssize_t rv = - EIO ;
214
+ ssize_t (* write )(struct file * , const char __user * , size_t , loff_t * );
215
+
216
+ spin_lock (& pde -> pde_unload_lock );
217
+ if (!pde -> proc_fops ) {
218
+ spin_unlock (& pde -> pde_unload_lock );
219
+ return rv ;
220
+ }
221
+ pde -> pde_users ++ ;
222
+ write = pde -> proc_fops -> write ;
223
+ spin_unlock (& pde -> pde_unload_lock );
224
+
225
+ if (write )
226
+ rv = write (file , buf , count , ppos );
227
+
228
+ pde_users_dec (pde );
229
+ return rv ;
230
+ }
231
+
232
+ static unsigned int proc_reg_poll (struct file * file , struct poll_table_struct * pts )
233
+ {
234
+ struct proc_dir_entry * pde = PDE (file -> f_path .dentry -> d_inode );
235
+ unsigned int rv = 0 ;
236
+ unsigned int (* poll )(struct file * , struct poll_table_struct * );
237
+
238
+ spin_lock (& pde -> pde_unload_lock );
239
+ if (!pde -> proc_fops ) {
240
+ spin_unlock (& pde -> pde_unload_lock );
241
+ return rv ;
242
+ }
243
+ pde -> pde_users ++ ;
244
+ poll = pde -> proc_fops -> poll ;
245
+ spin_unlock (& pde -> pde_unload_lock );
246
+
247
+ if (poll )
248
+ rv = poll (file , pts );
249
+
250
+ pde_users_dec (pde );
251
+ return rv ;
252
+ }
253
+
254
+ static long proc_reg_unlocked_ioctl (struct file * file , unsigned int cmd , unsigned long arg )
255
+ {
256
+ struct proc_dir_entry * pde = PDE (file -> f_path .dentry -> d_inode );
257
+ long rv = - ENOTTY ;
258
+ long (* unlocked_ioctl )(struct file * , unsigned int , unsigned long );
259
+ int (* ioctl )(struct inode * , struct file * , unsigned int , unsigned long );
260
+
261
+ spin_lock (& pde -> pde_unload_lock );
262
+ if (!pde -> proc_fops ) {
263
+ spin_unlock (& pde -> pde_unload_lock );
264
+ return rv ;
265
+ }
266
+ pde -> pde_users ++ ;
267
+ unlocked_ioctl = pde -> proc_fops -> unlocked_ioctl ;
268
+ ioctl = pde -> proc_fops -> ioctl ;
269
+ spin_unlock (& pde -> pde_unload_lock );
270
+
271
+ if (unlocked_ioctl ) {
272
+ rv = unlocked_ioctl (file , cmd , arg );
273
+ if (rv == - ENOIOCTLCMD )
274
+ rv = - EINVAL ;
275
+ } else if (ioctl ) {
276
+ lock_kernel ();
277
+ rv = ioctl (file -> f_path .dentry -> d_inode , file , cmd , arg );
278
+ unlock_kernel ();
279
+ }
280
+
281
+ pde_users_dec (pde );
282
+ return rv ;
283
+ }
284
+
285
+ #ifdef CONFIG_COMPAT
286
+ static long proc_reg_compat_ioctl (struct file * file , unsigned int cmd , unsigned long arg )
287
+ {
288
+ struct proc_dir_entry * pde = PDE (file -> f_path .dentry -> d_inode );
289
+ long rv = - ENOTTY ;
290
+ long (* compat_ioctl )(struct file * , unsigned int , unsigned long );
291
+
292
+ spin_lock (& pde -> pde_unload_lock );
293
+ if (!pde -> proc_fops ) {
294
+ spin_unlock (& pde -> pde_unload_lock );
295
+ return rv ;
296
+ }
297
+ pde -> pde_users ++ ;
298
+ compat_ioctl = pde -> proc_fops -> compat_ioctl ;
299
+ spin_unlock (& pde -> pde_unload_lock );
300
+
301
+ if (compat_ioctl )
302
+ rv = compat_ioctl (file , cmd , arg );
303
+
304
+ pde_users_dec (pde );
305
+ return rv ;
306
+ }
307
+ #endif
308
+
309
+ static int proc_reg_mmap (struct file * file , struct vm_area_struct * vma )
310
+ {
311
+ struct proc_dir_entry * pde = PDE (file -> f_path .dentry -> d_inode );
312
+ int rv = - EIO ;
313
+ int (* mmap )(struct file * , struct vm_area_struct * );
314
+
315
+ spin_lock (& pde -> pde_unload_lock );
316
+ if (!pde -> proc_fops ) {
317
+ spin_unlock (& pde -> pde_unload_lock );
318
+ return rv ;
319
+ }
320
+ pde -> pde_users ++ ;
321
+ mmap = pde -> proc_fops -> mmap ;
322
+ spin_unlock (& pde -> pde_unload_lock );
323
+
324
+ if (mmap )
325
+ rv = mmap (file , vma );
326
+
327
+ pde_users_dec (pde );
328
+ return rv ;
329
+ }
330
+
331
+ static int proc_reg_open (struct inode * inode , struct file * file )
332
+ {
333
+ struct proc_dir_entry * pde = PDE (inode );
334
+ int rv = 0 ;
335
+ int (* open )(struct inode * , struct file * );
336
+
337
+ spin_lock (& pde -> pde_unload_lock );
338
+ if (!pde -> proc_fops ) {
339
+ spin_unlock (& pde -> pde_unload_lock );
340
+ return rv ;
341
+ }
342
+ pde -> pde_users ++ ;
343
+ open = pde -> proc_fops -> open ;
344
+ spin_unlock (& pde -> pde_unload_lock );
345
+
346
+ if (open )
347
+ rv = open (inode , file );
348
+
349
+ pde_users_dec (pde );
350
+ return rv ;
351
+ }
352
+
353
+ static int proc_reg_release (struct inode * inode , struct file * file )
354
+ {
355
+ struct proc_dir_entry * pde = PDE (inode );
356
+ int rv = 0 ;
357
+ int (* release )(struct inode * , struct file * );
358
+
359
+ spin_lock (& pde -> pde_unload_lock );
360
+ if (!pde -> proc_fops ) {
361
+ spin_unlock (& pde -> pde_unload_lock );
362
+ return rv ;
363
+ }
364
+ pde -> pde_users ++ ;
365
+ release = pde -> proc_fops -> release ;
366
+ spin_unlock (& pde -> pde_unload_lock );
367
+
368
+ if (release )
369
+ rv = release (inode , file );
370
+
371
+ pde_users_dec (pde );
372
+ return rv ;
373
+ }
374
+
375
+ static const struct file_operations proc_reg_file_ops = {
376
+ .llseek = proc_reg_llseek ,
377
+ .read = proc_reg_read ,
378
+ .write = proc_reg_write ,
379
+ .poll = proc_reg_poll ,
380
+ .unlocked_ioctl = proc_reg_unlocked_ioctl ,
381
+ #ifdef CONFIG_COMPAT
382
+ .compat_ioctl = proc_reg_compat_ioctl ,
383
+ #endif
384
+ .mmap = proc_reg_mmap ,
385
+ .open = proc_reg_open ,
386
+ .release = proc_reg_release ,
387
+ };
388
+
143
389
struct inode * proc_get_inode (struct super_block * sb , unsigned int ino ,
144
390
struct proc_dir_entry * de )
145
391
{
@@ -166,8 +412,12 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
166
412
inode -> i_nlink = de -> nlink ;
167
413
if (de -> proc_iops )
168
414
inode -> i_op = de -> proc_iops ;
169
- if (de -> proc_fops )
170
- inode -> i_fop = de -> proc_fops ;
415
+ if (de -> proc_fops ) {
416
+ if (S_ISREG (inode -> i_mode ))
417
+ inode -> i_fop = & proc_reg_file_ops ;
418
+ else
419
+ inode -> i_fop = de -> proc_fops ;
420
+ }
171
421
}
172
422
173
423
return inode ;
0 commit comments