inode.c (cc31004a4aa784d89054ec07b87eae05cecf7121) inode.c (eae473581cf93dad94ca833aa961c033c6a43924)
1/*
2 * inode.c - part of tracefs, a pseudo file system for activating tracing
3 *
4 * Based on debugfs by: Greg Kroah-Hartman <greg@kroah.com>
5 *
6 * Copyright (C) 2014 Red Hat Inc, author: Steven Rostedt <srostedt@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or

--- 36 unchanged lines hidden (view full) ---

45
46static const struct file_operations tracefs_file_operations = {
47 .read = default_read_file,
48 .write = default_write_file,
49 .open = simple_open,
50 .llseek = noop_llseek,
51};
52
1/*
2 * inode.c - part of tracefs, a pseudo file system for activating tracing
3 *
4 * Based on debugfs by: Greg Kroah-Hartman <greg@kroah.com>
5 *
6 * Copyright (C) 2014 Red Hat Inc, author: Steven Rostedt <srostedt@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or

--- 36 unchanged lines hidden (view full) ---

45
46static const struct file_operations tracefs_file_operations = {
47 .read = default_read_file,
48 .write = default_write_file,
49 .open = simple_open,
50 .llseek = noop_llseek,
51};
52
53static struct tracefs_dir_ops {
54 int (*mkdir)(const char *name);
55 int (*rmdir)(const char *name);
56} tracefs_ops;
57
58static char *get_dname(struct dentry *dentry)
59{
60 const char *dname;
61 char *name;
62 int len = dentry->d_name.len;
63
64 dname = dentry->d_name.name;
65 name = kmalloc(len + 1, GFP_KERNEL);
66 if (!name)
67 return NULL;
68 memcpy(name, dname, len);
69 name[len] = 0;
70 return name;
71}
72
73static int tracefs_syscall_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode)
74{
75 char *name;
76 int ret;
77
78 name = get_dname(dentry);
79 if (!name)
80 return -ENOMEM;
81
82 /*
83 * The mkdir call can call the generic functions that create
84 * the files within the tracefs system. It is up to the individual
85 * mkdir routine to handle races.
86 */
87 mutex_unlock(&inode->i_mutex);
88 ret = tracefs_ops.mkdir(name);
89 mutex_lock(&inode->i_mutex);
90
91 kfree(name);
92
93 return ret;
94}
95
96static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry)
97{
98 char *name;
99 int ret;
100
101 name = get_dname(dentry);
102 if (!name)
103 return -ENOMEM;
104
105 /*
106 * The rmdir call can call the generic functions that create
107 * the files within the tracefs system. It is up to the individual
108 * rmdir routine to handle races.
109 * This time we need to unlock not only the parent (inode) but
110 * also the directory that is being deleted.
111 */
112 mutex_unlock(&inode->i_mutex);
113 mutex_unlock(&dentry->d_inode->i_mutex);
114
115 ret = tracefs_ops.rmdir(name);
116
117 mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
118 mutex_lock(&dentry->d_inode->i_mutex);
119
120 kfree(name);
121
122 return ret;
123}
124
125static const struct inode_operations tracefs_dir_inode_operations = {
126 .lookup = simple_lookup,
127 .mkdir = tracefs_syscall_mkdir,
128 .rmdir = tracefs_syscall_rmdir,
129};
130
53static struct inode *tracefs_get_inode(struct super_block *sb)
54{
55 struct inode *inode = new_inode(sb);
56 if (inode) {
57 inode->i_ino = get_next_ino();
58 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
59 }
60 return inode;

--- 268 unchanged lines hidden (view full) ---

329 inode->i_mode = mode;
330 inode->i_fop = fops ? fops : &tracefs_file_operations;
331 inode->i_private = data;
332 d_instantiate(dentry, inode);
333 fsnotify_create(dentry->d_parent->d_inode, dentry);
334 return end_creating(dentry);
335}
336
131static struct inode *tracefs_get_inode(struct super_block *sb)
132{
133 struct inode *inode = new_inode(sb);
134 if (inode) {
135 inode->i_ino = get_next_ino();
136 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
137 }
138 return inode;

--- 268 unchanged lines hidden (view full) ---

407 inode->i_mode = mode;
408 inode->i_fop = fops ? fops : &tracefs_file_operations;
409 inode->i_private = data;
410 d_instantiate(dentry, inode);
411 fsnotify_create(dentry->d_parent->d_inode, dentry);
412 return end_creating(dentry);
413}
414
415static struct dentry *__create_dir(const char *name, struct dentry *parent,
416 const struct inode_operations *ops)
417{
418 struct dentry *dentry = start_creating(name, parent);
419 struct inode *inode;
420
421 if (IS_ERR(dentry))
422 return NULL;
423
424 inode = tracefs_get_inode(dentry->d_sb);
425 if (unlikely(!inode))
426 return failed_creating(dentry);
427
428 inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
429 inode->i_op = ops;
430 inode->i_fop = &simple_dir_operations;
431
432 /* directory inodes start off with i_nlink == 2 (for "." entry) */
433 inc_nlink(inode);
434 d_instantiate(dentry, inode);
435 inc_nlink(dentry->d_parent->d_inode);
436 fsnotify_mkdir(dentry->d_parent->d_inode, dentry);
437 return end_creating(dentry);
438}
439
337/**
338 * tracefs_create_dir - create a directory in the tracefs filesystem
339 * @name: a pointer to a string containing the name of the directory to
340 * create.
341 * @parent: a pointer to the parent dentry for this file. This should be a
342 * directory dentry if set. If this parameter is NULL, then the
343 * directory will be created in the root of the tracefs filesystem.
344 *
345 * This function creates a directory in tracefs with the given name.
346 *
347 * This function will return a pointer to a dentry if it succeeds. This
348 * pointer must be passed to the tracefs_remove() function when the file is
349 * to be removed. If an error occurs, %NULL will be returned.
350 *
351 * If tracing is not enabled in the kernel, the value -%ENODEV will be
352 * returned.
353 */
354struct dentry *tracefs_create_dir(const char *name, struct dentry *parent)
355{
440/**
441 * tracefs_create_dir - create a directory in the tracefs filesystem
442 * @name: a pointer to a string containing the name of the directory to
443 * create.
444 * @parent: a pointer to the parent dentry for this file. This should be a
445 * directory dentry if set. If this parameter is NULL, then the
446 * directory will be created in the root of the tracefs filesystem.
447 *
448 * This function creates a directory in tracefs with the given name.
449 *
450 * This function will return a pointer to a dentry if it succeeds. This
451 * pointer must be passed to the tracefs_remove() function when the file is
452 * to be removed. If an error occurs, %NULL will be returned.
453 *
454 * If tracing is not enabled in the kernel, the value -%ENODEV will be
455 * returned.
456 */
457struct dentry *tracefs_create_dir(const char *name, struct dentry *parent)
458{
356 struct dentry *dentry = start_creating(name, parent);
357 struct inode *inode;
459 return __create_dir(name, parent, &simple_dir_inode_operations);
460}
358
461
359 if (IS_ERR(dentry))
462/**
463 * tracefs_create_instance_dir - create the tracing instances directory
464 * @name: The name of the instances directory to create
465 * @parent: The parent directory that the instances directory will exist
466 * @mkdir: The function to call when a mkdir is performed.
467 * @rmdir: The function to call when a rmdir is performed.
468 *
469 * Only one instances directory is allowed.
470 *
471 * The instances directory is special as it allows for mkdir and rmdir to
472 * to be done by userspace. When a mkdir or rmdir is performed, the inode
473 * locks are released and the methhods passed in (@mkdir and @rmdir) are
474 * called without locks and with the name of the directory being created
475 * within the instances directory.
476 *
477 * Returns the dentry of the instances directory.
478 */
479struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *parent,
480 int (*mkdir)(const char *name),
481 int (*rmdir)(const char *name))
482{
483 struct dentry *dentry;
484
485 /* Only allow one instance of the instances directory. */
486 if (WARN_ON(tracefs_ops.mkdir || tracefs_ops.rmdir))
360 return NULL;
361
487 return NULL;
488
362 inode = tracefs_get_inode(dentry->d_sb);
363 if (unlikely(!inode))
364 return failed_creating(dentry);
489 dentry = __create_dir(name, parent, &tracefs_dir_inode_operations);
490 if (!dentry)
491 return NULL;
365
492
366 inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
367 inode->i_op = &simple_dir_inode_operations;
368 inode->i_fop = &simple_dir_operations;
493 tracefs_ops.mkdir = mkdir;
494 tracefs_ops.rmdir = rmdir;
369
495
370 /* directory inodes start off with i_nlink == 2 (for "." entry) */
371 inc_nlink(inode);
372 d_instantiate(dentry, inode);
373 inc_nlink(dentry->d_parent->d_inode);
374 fsnotify_mkdir(dentry->d_parent->d_inode, dentry);
375 return end_creating(dentry);
496 return dentry;
376}
377
378static inline int tracefs_positive(struct dentry *dentry)
379{
380 return dentry->d_inode && !d_unhashed(dentry);
381}
382
383static int __tracefs_remove(struct dentry *dentry, struct dentry *parent)

--- 146 unchanged lines hidden ---
497}
498
499static inline int tracefs_positive(struct dentry *dentry)
500{
501 return dentry->d_inode && !d_unhashed(dentry);
502}
503
504static int __tracefs_remove(struct dentry *dentry, struct dentry *parent)

--- 146 unchanged lines hidden ---