diff options
| -rw-r--r-- | Documentation/filesystems/Locking | 2 | ||||
| -rw-r--r-- | Documentation/filesystems/vfs.txt | 23 | ||||
| -rw-r--r-- | fs/dcache.c | 31 | ||||
| -rw-r--r-- | fs/pipe.c | 18 | ||||
| -rw-r--r-- | include/linux/dcache.h | 6 | ||||
| -rw-r--r-- | net/socket.c | 20 |
6 files changed, 86 insertions, 14 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 28bfea75bcf2..59c14159cc47 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
| @@ -15,6 +15,7 @@ prototypes: | |||
| 15 | int (*d_delete)(struct dentry *); | 15 | int (*d_delete)(struct dentry *); |
| 16 | void (*d_release)(struct dentry *); | 16 | void (*d_release)(struct dentry *); |
| 17 | void (*d_iput)(struct dentry *, struct inode *); | 17 | void (*d_iput)(struct dentry *, struct inode *); |
| 18 | char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); | ||
| 18 | 19 | ||
| 19 | locking rules: | 20 | locking rules: |
| 20 | none have BKL | 21 | none have BKL |
| @@ -25,6 +26,7 @@ d_compare: no yes no no | |||
| 25 | d_delete: yes no yes no | 26 | d_delete: yes no yes no |
| 26 | d_release: no no no yes | 27 | d_release: no no no yes |
| 27 | d_iput: no no no yes | 28 | d_iput: no no no yes |
| 29 | d_dname: no no no no | ||
| 28 | 30 | ||
| 29 | --------------------------- inode_operations --------------------------- | 31 | --------------------------- inode_operations --------------------------- |
| 30 | prototypes: | 32 | prototypes: |
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index ea271f2d3954..a47cc819f37b 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
| @@ -827,7 +827,7 @@ This describes how a filesystem can overload the standard dentry | |||
| 827 | operations. Dentries and the dcache are the domain of the VFS and the | 827 | operations. Dentries and the dcache are the domain of the VFS and the |
| 828 | individual filesystem implementations. Device drivers have no business | 828 | individual filesystem implementations. Device drivers have no business |
| 829 | here. These methods may be set to NULL, as they are either optional or | 829 | here. These methods may be set to NULL, as they are either optional or |
| 830 | the VFS uses a default. As of kernel 2.6.13, the following members are | 830 | the VFS uses a default. As of kernel 2.6.22, the following members are |
| 831 | defined: | 831 | defined: |
| 832 | 832 | ||
| 833 | struct dentry_operations { | 833 | struct dentry_operations { |
| @@ -837,6 +837,7 @@ struct dentry_operations { | |||
| 837 | int (*d_delete)(struct dentry *); | 837 | int (*d_delete)(struct dentry *); |
| 838 | void (*d_release)(struct dentry *); | 838 | void (*d_release)(struct dentry *); |
| 839 | void (*d_iput)(struct dentry *, struct inode *); | 839 | void (*d_iput)(struct dentry *, struct inode *); |
| 840 | char *(*d_dname)(struct dentry *, char *, int); | ||
| 840 | }; | 841 | }; |
| 841 | 842 | ||
| 842 | d_revalidate: called when the VFS needs to revalidate a dentry. This | 843 | d_revalidate: called when the VFS needs to revalidate a dentry. This |
| @@ -859,6 +860,26 @@ struct dentry_operations { | |||
| 859 | VFS calls iput(). If you define this method, you must call | 860 | VFS calls iput(). If you define this method, you must call |
| 860 | iput() yourself | 861 | iput() yourself |
| 861 | 862 | ||
| 863 | d_dname: called when the pathname of a dentry should be generated. | ||
| 864 | Usefull for some pseudo filesystems (sockfs, pipefs, ...) to delay | ||
| 865 | pathname generation. (Instead of doing it when dentry is created, | ||
| 866 | its done only when the path is needed.). Real filesystems probably | ||
| 867 | dont want to use it, because their dentries are present in global | ||
| 868 | dcache hash, so their hash should be an invariant. As no lock is | ||
| 869 | held, d_dname() should not try to modify the dentry itself, unless | ||
| 870 | appropriate SMP safety is used. CAUTION : d_path() logic is quite | ||
| 871 | tricky. The correct way to return for example "Hello" is to put it | ||
| 872 | at the end of the buffer, and returns a pointer to the first char. | ||
| 873 | dynamic_dname() helper function is provided to take care of this. | ||
| 874 | |||
| 875 | Example : | ||
| 876 | |||
| 877 | static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) | ||
| 878 | { | ||
| 879 | return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", | ||
| 880 | dentry->d_inode->i_ino); | ||
| 881 | } | ||
| 882 | |||
| 862 | Each dentry has a pointer to its parent dentry, as well as a hash list | 883 | Each dentry has a pointer to its parent dentry, as well as a hash list |
| 863 | of child dentries. Child dentries are basically like files in a | 884 | of child dentries. Child dentries are basically like files in a |
| 864 | directory. | 885 | directory. |
diff --git a/fs/dcache.c b/fs/dcache.c index 268da2e2bc09..2135ab8bb103 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -1853,6 +1853,16 @@ char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt, | |||
| 1853 | struct vfsmount *rootmnt; | 1853 | struct vfsmount *rootmnt; |
| 1854 | struct dentry *root; | 1854 | struct dentry *root; |
| 1855 | 1855 | ||
| 1856 | /* | ||
| 1857 | * We have various synthetic filesystems that never get mounted. On | ||
| 1858 | * these filesystems dentries are never used for lookup purposes, and | ||
| 1859 | * thus don't need to be hashed. They also don't need a name until a | ||
| 1860 | * user wants to identify the object in /proc/pid/fd/. The little hack | ||
| 1861 | * below allows us to generate a name for these objects on demand: | ||
| 1862 | */ | ||
| 1863 | if (dentry->d_op && dentry->d_op->d_dname) | ||
| 1864 | return dentry->d_op->d_dname(dentry, buf, buflen); | ||
| 1865 | |||
| 1856 | read_lock(¤t->fs->lock); | 1866 | read_lock(¤t->fs->lock); |
| 1857 | rootmnt = mntget(current->fs->rootmnt); | 1867 | rootmnt = mntget(current->fs->rootmnt); |
| 1858 | root = dget(current->fs->root); | 1868 | root = dget(current->fs->root); |
| @@ -1866,6 +1876,27 @@ char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt, | |||
| 1866 | } | 1876 | } |
| 1867 | 1877 | ||
| 1868 | /* | 1878 | /* |
| 1879 | * Helper function for dentry_operations.d_dname() members | ||
| 1880 | */ | ||
| 1881 | char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen, | ||
| 1882 | const char *fmt, ...) | ||
| 1883 | { | ||
| 1884 | va_list args; | ||
| 1885 | char temp[64]; | ||
| 1886 | int sz; | ||
| 1887 | |||
| 1888 | va_start(args, fmt); | ||
| 1889 | sz = vsnprintf(temp, sizeof(temp), fmt, args) + 1; | ||
| 1890 | va_end(args); | ||
| 1891 | |||
| 1892 | if (sz > sizeof(temp) || sz > buflen) | ||
| 1893 | return ERR_PTR(-ENAMETOOLONG); | ||
| 1894 | |||
| 1895 | buffer += buflen - sz; | ||
| 1896 | return memcpy(buffer, temp, sz); | ||
| 1897 | } | ||
| 1898 | |||
| 1899 | /* | ||
| 1869 | * NOTE! The user-level library version returns a | 1900 | * NOTE! The user-level library version returns a |
| 1870 | * character pointer. The kernel system call just | 1901 | * character pointer. The kernel system call just |
| 1871 | * returns the length of the buffer filled (which | 1902 | * returns the length of the buffer filled (which |
| @@ -841,8 +841,18 @@ static int pipefs_delete_dentry(struct dentry *dentry) | |||
| 841 | return 0; | 841 | return 0; |
| 842 | } | 842 | } |
| 843 | 843 | ||
| 844 | /* | ||
| 845 | * pipefs_dname() is called from d_path(). | ||
| 846 | */ | ||
| 847 | static char *pipefs_dname(struct dentry *dentry, char *buffer, int buflen) | ||
| 848 | { | ||
| 849 | return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", | ||
| 850 | dentry->d_inode->i_ino); | ||
| 851 | } | ||
| 852 | |||
| 844 | static struct dentry_operations pipefs_dentry_operations = { | 853 | static struct dentry_operations pipefs_dentry_operations = { |
| 845 | .d_delete = pipefs_delete_dentry, | 854 | .d_delete = pipefs_delete_dentry, |
| 855 | .d_dname = pipefs_dname, | ||
| 846 | }; | 856 | }; |
| 847 | 857 | ||
| 848 | static struct inode * get_pipe_inode(void) | 858 | static struct inode * get_pipe_inode(void) |
| @@ -888,8 +898,7 @@ struct file *create_write_pipe(void) | |||
| 888 | struct inode *inode; | 898 | struct inode *inode; |
| 889 | struct file *f; | 899 | struct file *f; |
| 890 | struct dentry *dentry; | 900 | struct dentry *dentry; |
| 891 | char name[32]; | 901 | struct qstr name = { .name = "" }; |
| 892 | struct qstr this; | ||
| 893 | 902 | ||
| 894 | f = get_empty_filp(); | 903 | f = get_empty_filp(); |
| 895 | if (!f) | 904 | if (!f) |
| @@ -899,11 +908,8 @@ struct file *create_write_pipe(void) | |||
| 899 | if (!inode) | 908 | if (!inode) |
| 900 | goto err_file; | 909 | goto err_file; |
| 901 | 910 | ||
| 902 | this.len = sprintf(name, "[%lu]", inode->i_ino); | ||
| 903 | this.name = name; | ||
| 904 | this.hash = 0; | ||
| 905 | err = -ENOMEM; | 911 | err = -ENOMEM; |
| 906 | dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this); | 912 | dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name); |
| 907 | if (!dentry) | 913 | if (!dentry) |
| 908 | goto err_inode; | 914 | goto err_inode; |
| 909 | 915 | ||
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 63f64a9a5bf7..aab53df4fafa 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
| @@ -133,6 +133,7 @@ struct dentry_operations { | |||
| 133 | int (*d_delete)(struct dentry *); | 133 | int (*d_delete)(struct dentry *); |
| 134 | void (*d_release)(struct dentry *); | 134 | void (*d_release)(struct dentry *); |
| 135 | void (*d_iput)(struct dentry *, struct inode *); | 135 | void (*d_iput)(struct dentry *, struct inode *); |
| 136 | char *(*d_dname)(struct dentry *, char *, int); | ||
| 136 | }; | 137 | }; |
| 137 | 138 | ||
| 138 | /* the dentry parameter passed to d_hash and d_compare is the parent | 139 | /* the dentry parameter passed to d_hash and d_compare is the parent |
| @@ -293,6 +294,11 @@ extern struct dentry * d_hash_and_lookup(struct dentry *, struct qstr *); | |||
| 293 | /* validate "insecure" dentry pointer */ | 294 | /* validate "insecure" dentry pointer */ |
| 294 | extern int d_validate(struct dentry *, struct dentry *); | 295 | extern int d_validate(struct dentry *, struct dentry *); |
| 295 | 296 | ||
| 297 | /* | ||
| 298 | * helper function for dentry_operations.d_dname() members | ||
| 299 | */ | ||
| 300 | extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); | ||
| 301 | |||
| 296 | extern char * d_path(struct dentry *, struct vfsmount *, char *, int); | 302 | extern char * d_path(struct dentry *, struct vfsmount *, char *, int); |
| 297 | 303 | ||
| 298 | /* Allocation counts.. */ | 304 | /* Allocation counts.. */ |
diff --git a/net/socket.c b/net/socket.c index 759825b7ca26..98a8f67abbfc 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -313,8 +313,19 @@ static int sockfs_delete_dentry(struct dentry *dentry) | |||
| 313 | dentry->d_flags |= DCACHE_UNHASHED; | 313 | dentry->d_flags |= DCACHE_UNHASHED; |
| 314 | return 0; | 314 | return 0; |
| 315 | } | 315 | } |
| 316 | |||
| 317 | /* | ||
| 318 | * sockfs_dname() is called from d_path(). | ||
| 319 | */ | ||
| 320 | static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) | ||
| 321 | { | ||
| 322 | return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", | ||
| 323 | dentry->d_inode->i_ino); | ||
| 324 | } | ||
| 325 | |||
| 316 | static struct dentry_operations sockfs_dentry_operations = { | 326 | static struct dentry_operations sockfs_dentry_operations = { |
| 317 | .d_delete = sockfs_delete_dentry, | 327 | .d_delete = sockfs_delete_dentry, |
| 328 | .d_dname = sockfs_dname, | ||
| 318 | }; | 329 | }; |
| 319 | 330 | ||
| 320 | /* | 331 | /* |
| @@ -354,14 +365,9 @@ static int sock_alloc_fd(struct file **filep) | |||
| 354 | 365 | ||
| 355 | static int sock_attach_fd(struct socket *sock, struct file *file) | 366 | static int sock_attach_fd(struct socket *sock, struct file *file) |
| 356 | { | 367 | { |
| 357 | struct qstr this; | 368 | struct qstr name = { .name = "" }; |
| 358 | char name[32]; | ||
| 359 | |||
| 360 | this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino); | ||
| 361 | this.name = name; | ||
| 362 | this.hash = 0; | ||
| 363 | 369 | ||
| 364 | file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); | 370 | file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); |
| 365 | if (unlikely(!file->f_path.dentry)) | 371 | if (unlikely(!file->f_path.dentry)) |
| 366 | return -ENOMEM; | 372 | return -ENOMEM; |
| 367 | 373 | ||
