Loading Documentation/filesystems/Locking +3 −2 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,8 @@ prototypes: char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); struct vfsmount *(*d_automount)(struct path *path); struct vfsmount *(*d_automount)(struct path *path); int (*d_manage)(struct dentry *, bool); int (*d_manage)(struct dentry *, bool); struct dentry *(*d_real)(struct dentry *, const struct inode *, unsigned int); locking rules: locking rules: rename_lock ->d_lock may block rcu-walk rename_lock ->d_lock may block rcu-walk Loading @@ -34,6 +36,7 @@ d_iput: no no yes no d_dname: no no no no d_dname: no no no no d_automount: no no yes no d_automount: no no yes no d_manage: no no yes (ref-walk) maybe d_manage: no no yes (ref-walk) maybe d_real no no yes no --------------------------- inode_operations --------------------------- --------------------------- inode_operations --------------------------- prototypes: prototypes: Loading Loading @@ -66,7 +69,6 @@ prototypes: struct file *, unsigned open_flag, struct file *, unsigned open_flag, umode_t create_mode, int *opened); umode_t create_mode, int *opened); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*dentry_open)(struct dentry *, struct file *, const struct cred *); locking rules: locking rules: all may block all may block Loading Loading @@ -95,7 +97,6 @@ fiemap: no update_time: no update_time: no atomic_open: yes atomic_open: yes tmpfile: no tmpfile: no dentry_open: no Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on victim. victim. Loading Documentation/filesystems/vfs.txt +26 −14 Original line number Original line Diff line number Diff line Loading @@ -364,7 +364,6 @@ struct inode_operations { int (*atomic_open)(struct inode *, struct dentry *, struct file *, int (*atomic_open)(struct inode *, struct dentry *, struct file *, unsigned open_flag, umode_t create_mode, int *opened); unsigned open_flag, umode_t create_mode, int *opened); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*dentry_open)(struct dentry *, struct file *, const struct cred *); }; }; Again, all methods are called without any locks being held, unless Again, all methods are called without any locks being held, unless Loading Loading @@ -696,13 +695,6 @@ struct address_space_operations { but instead uses bmap to find out where the blocks in the file but instead uses bmap to find out where the blocks in the file are and uses those addresses directly. are and uses those addresses directly. dentry_open: *WARNING: probably going away soon, do not use!* This is an alternative to f_op->open(), the difference is that this method may open a file not necessarily originating from the same filesystem as the one i_op->open() was called on. It may be useful for stacking filesystems which want to allow native I/O directly on underlying files. invalidatepage: If a page has PagePrivate set, then invalidatepage invalidatepage: If a page has PagePrivate set, then invalidatepage will be called when part or all of the page is to be removed will be called when part or all of the page is to be removed from the address space. This generally corresponds to either a from the address space. This generally corresponds to either a Loading Loading @@ -938,6 +930,8 @@ struct dentry_operations { char *(*d_dname)(struct dentry *, char *, int); char *(*d_dname)(struct dentry *, char *, int); struct vfsmount *(*d_automount)(struct path *); struct vfsmount *(*d_automount)(struct path *); int (*d_manage)(struct dentry *, bool); int (*d_manage)(struct dentry *, bool); struct dentry *(*d_real)(struct dentry *, const struct inode *, unsigned int); }; }; d_revalidate: called when the VFS needs to revalidate a dentry. This d_revalidate: called when the VFS needs to revalidate a dentry. This Loading Loading @@ -1022,6 +1016,14 @@ struct dentry_operations { at the end of the buffer, and returns a pointer to the first char. at the end of the buffer, and returns a pointer to the first char. dynamic_dname() helper function is provided to take care of this. dynamic_dname() helper function is provided to take care of this. Example : static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) { return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", dentry->d_inode->i_ino); } d_automount: called when an automount dentry is to be traversed (optional). d_automount: called when an automount dentry is to be traversed (optional). This should create a new VFS mount record and return the record to the This should create a new VFS mount record and return the record to the caller. The caller is supplied with a path parameter giving the caller. The caller is supplied with a path parameter giving the Loading Loading @@ -1060,13 +1062,23 @@ struct dentry_operations { This function is only used if DCACHE_MANAGE_TRANSIT is set on the This function is only used if DCACHE_MANAGE_TRANSIT is set on the dentry being transited from. dentry being transited from. Example : d_real: overlay/union type filesystems implement this method to return one of the underlying dentries hidden by the overlay. It is used in three different modes: static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) Called from open it may need to copy-up the file depending on the { supplied open flags. This mode is selected with a non-zero flags return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", argument. In this mode the d_real method can return an error. dentry->d_inode->i_ino); } Called from file_dentry() it returns the real dentry matching the inode argument. The real dentry may be from a lower layer already copied up, but still referenced from the file. This mode is selected with a non-NULL inode argument. This will always succeed. With NULL inode and zero flags the topmost real underlying dentry is returned. This will always succeed. This method is never called with both non-NULL inode and non-zero flags. Each dentry has a pointer to its parent dentry, as well as a hash list Each dentry has a pointer to its parent dentry, as well as a hash list of child dentries. Child dentries are basically like files in a of child dentries. Child dentries are basically like files in a Loading fs/dcache.c +0 −3 Original line number Original line Diff line number Diff line Loading @@ -1729,7 +1729,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) DCACHE_OP_REVALIDATE | DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_DELETE | DCACHE_OP_DELETE | DCACHE_OP_SELECT_INODE | DCACHE_OP_REAL)); DCACHE_OP_REAL)); dentry->d_op = op; dentry->d_op = op; if (!op) if (!op) Loading @@ -1746,8 +1745,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) dentry->d_flags |= DCACHE_OP_DELETE; dentry->d_flags |= DCACHE_OP_DELETE; if (op->d_prune) if (op->d_prune) dentry->d_flags |= DCACHE_OP_PRUNE; dentry->d_flags |= DCACHE_OP_PRUNE; if (op->d_select_inode) dentry->d_flags |= DCACHE_OP_SELECT_INODE; if (op->d_real) if (op->d_real) dentry->d_flags |= DCACHE_OP_REAL; dentry->d_flags |= DCACHE_OP_REAL; Loading fs/namei.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -4328,7 +4328,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, * Check source == target. * Check source == target. * On overlayfs need to look at underlying inodes. * On overlayfs need to look at underlying inodes. */ */ if (vfs_select_inode(old_dentry, 0) == vfs_select_inode(new_dentry, 0)) if (d_real_inode(old_dentry) == d_real_inode(new_dentry)) return 0; return 0; error = may_delete(old_dir, old_dentry, is_dir); error = may_delete(old_dir, old_dentry, is_dir); Loading fs/open.c +4 −4 Original line number Original line Diff line number Diff line Loading @@ -840,13 +840,13 @@ EXPORT_SYMBOL(file_path); int vfs_open(const struct path *path, struct file *file, int vfs_open(const struct path *path, struct file *file, const struct cred *cred) const struct cred *cred) { { struct inode *inode = vfs_select_inode(path->dentry, file->f_flags); struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags); if (IS_ERR(inode)) if (IS_ERR(dentry)) return PTR_ERR(inode); return PTR_ERR(dentry); file->f_path = *path; file->f_path = *path; return do_dentry_open(file, inode, NULL, cred); return do_dentry_open(file, d_backing_inode(dentry), NULL, cred); } } struct file *dentry_open(const struct path *path, int flags, struct file *dentry_open(const struct path *path, int flags, Loading Loading
Documentation/filesystems/Locking +3 −2 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,8 @@ prototypes: char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); struct vfsmount *(*d_automount)(struct path *path); struct vfsmount *(*d_automount)(struct path *path); int (*d_manage)(struct dentry *, bool); int (*d_manage)(struct dentry *, bool); struct dentry *(*d_real)(struct dentry *, const struct inode *, unsigned int); locking rules: locking rules: rename_lock ->d_lock may block rcu-walk rename_lock ->d_lock may block rcu-walk Loading @@ -34,6 +36,7 @@ d_iput: no no yes no d_dname: no no no no d_dname: no no no no d_automount: no no yes no d_automount: no no yes no d_manage: no no yes (ref-walk) maybe d_manage: no no yes (ref-walk) maybe d_real no no yes no --------------------------- inode_operations --------------------------- --------------------------- inode_operations --------------------------- prototypes: prototypes: Loading Loading @@ -66,7 +69,6 @@ prototypes: struct file *, unsigned open_flag, struct file *, unsigned open_flag, umode_t create_mode, int *opened); umode_t create_mode, int *opened); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*dentry_open)(struct dentry *, struct file *, const struct cred *); locking rules: locking rules: all may block all may block Loading Loading @@ -95,7 +97,6 @@ fiemap: no update_time: no update_time: no atomic_open: yes atomic_open: yes tmpfile: no tmpfile: no dentry_open: no Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on victim. victim. Loading
Documentation/filesystems/vfs.txt +26 −14 Original line number Original line Diff line number Diff line Loading @@ -364,7 +364,6 @@ struct inode_operations { int (*atomic_open)(struct inode *, struct dentry *, struct file *, int (*atomic_open)(struct inode *, struct dentry *, struct file *, unsigned open_flag, umode_t create_mode, int *opened); unsigned open_flag, umode_t create_mode, int *opened); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*dentry_open)(struct dentry *, struct file *, const struct cred *); }; }; Again, all methods are called without any locks being held, unless Again, all methods are called without any locks being held, unless Loading Loading @@ -696,13 +695,6 @@ struct address_space_operations { but instead uses bmap to find out where the blocks in the file but instead uses bmap to find out where the blocks in the file are and uses those addresses directly. are and uses those addresses directly. dentry_open: *WARNING: probably going away soon, do not use!* This is an alternative to f_op->open(), the difference is that this method may open a file not necessarily originating from the same filesystem as the one i_op->open() was called on. It may be useful for stacking filesystems which want to allow native I/O directly on underlying files. invalidatepage: If a page has PagePrivate set, then invalidatepage invalidatepage: If a page has PagePrivate set, then invalidatepage will be called when part or all of the page is to be removed will be called when part or all of the page is to be removed from the address space. This generally corresponds to either a from the address space. This generally corresponds to either a Loading Loading @@ -938,6 +930,8 @@ struct dentry_operations { char *(*d_dname)(struct dentry *, char *, int); char *(*d_dname)(struct dentry *, char *, int); struct vfsmount *(*d_automount)(struct path *); struct vfsmount *(*d_automount)(struct path *); int (*d_manage)(struct dentry *, bool); int (*d_manage)(struct dentry *, bool); struct dentry *(*d_real)(struct dentry *, const struct inode *, unsigned int); }; }; d_revalidate: called when the VFS needs to revalidate a dentry. This d_revalidate: called when the VFS needs to revalidate a dentry. This Loading Loading @@ -1022,6 +1016,14 @@ struct dentry_operations { at the end of the buffer, and returns a pointer to the first char. at the end of the buffer, and returns a pointer to the first char. dynamic_dname() helper function is provided to take care of this. dynamic_dname() helper function is provided to take care of this. Example : static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) { return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", dentry->d_inode->i_ino); } d_automount: called when an automount dentry is to be traversed (optional). d_automount: called when an automount dentry is to be traversed (optional). This should create a new VFS mount record and return the record to the This should create a new VFS mount record and return the record to the caller. The caller is supplied with a path parameter giving the caller. The caller is supplied with a path parameter giving the Loading Loading @@ -1060,13 +1062,23 @@ struct dentry_operations { This function is only used if DCACHE_MANAGE_TRANSIT is set on the This function is only used if DCACHE_MANAGE_TRANSIT is set on the dentry being transited from. dentry being transited from. Example : d_real: overlay/union type filesystems implement this method to return one of the underlying dentries hidden by the overlay. It is used in three different modes: static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) Called from open it may need to copy-up the file depending on the { supplied open flags. This mode is selected with a non-zero flags return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", argument. In this mode the d_real method can return an error. dentry->d_inode->i_ino); } Called from file_dentry() it returns the real dentry matching the inode argument. The real dentry may be from a lower layer already copied up, but still referenced from the file. This mode is selected with a non-NULL inode argument. This will always succeed. With NULL inode and zero flags the topmost real underlying dentry is returned. This will always succeed. This method is never called with both non-NULL inode and non-zero flags. Each dentry has a pointer to its parent dentry, as well as a hash list Each dentry has a pointer to its parent dentry, as well as a hash list of child dentries. Child dentries are basically like files in a of child dentries. Child dentries are basically like files in a Loading
fs/dcache.c +0 −3 Original line number Original line Diff line number Diff line Loading @@ -1729,7 +1729,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) DCACHE_OP_REVALIDATE | DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_DELETE | DCACHE_OP_DELETE | DCACHE_OP_SELECT_INODE | DCACHE_OP_REAL)); DCACHE_OP_REAL)); dentry->d_op = op; dentry->d_op = op; if (!op) if (!op) Loading @@ -1746,8 +1745,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) dentry->d_flags |= DCACHE_OP_DELETE; dentry->d_flags |= DCACHE_OP_DELETE; if (op->d_prune) if (op->d_prune) dentry->d_flags |= DCACHE_OP_PRUNE; dentry->d_flags |= DCACHE_OP_PRUNE; if (op->d_select_inode) dentry->d_flags |= DCACHE_OP_SELECT_INODE; if (op->d_real) if (op->d_real) dentry->d_flags |= DCACHE_OP_REAL; dentry->d_flags |= DCACHE_OP_REAL; Loading
fs/namei.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -4328,7 +4328,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, * Check source == target. * Check source == target. * On overlayfs need to look at underlying inodes. * On overlayfs need to look at underlying inodes. */ */ if (vfs_select_inode(old_dentry, 0) == vfs_select_inode(new_dentry, 0)) if (d_real_inode(old_dentry) == d_real_inode(new_dentry)) return 0; return 0; error = may_delete(old_dir, old_dentry, is_dir); error = may_delete(old_dir, old_dentry, is_dir); Loading
fs/open.c +4 −4 Original line number Original line Diff line number Diff line Loading @@ -840,13 +840,13 @@ EXPORT_SYMBOL(file_path); int vfs_open(const struct path *path, struct file *file, int vfs_open(const struct path *path, struct file *file, const struct cred *cred) const struct cred *cred) { { struct inode *inode = vfs_select_inode(path->dentry, file->f_flags); struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags); if (IS_ERR(inode)) if (IS_ERR(dentry)) return PTR_ERR(inode); return PTR_ERR(dentry); file->f_path = *path; file->f_path = *path; return do_dentry_open(file, inode, NULL, cred); return do_dentry_open(file, d_backing_inode(dentry), NULL, cred); } } struct file *dentry_open(const struct path *path, int flags, struct file *dentry_open(const struct path *path, int flags, Loading