2019-03-27 05:19:18

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 00/24] Convert vfs.txt to vfs.rst


Hi Al,

This series converts the VFS file Documentation/filesystems/vfs.txt to
reStructuredText format. Please consider taking this series through
your tree as apposed to Jon's tree because this set makes a fair amount
of changes to VFS files (and also the VFS tree and docs tree are out of
sync right now with the recent work by Mauro and Neil).

Excluding patch 2, this set is whitespace and documentation fixes only.

Why 25 patches to convert one simple file? There is a bunch of clean up
to VFS docs in here. I have attempted to make review easier by breaking
changes into very discreet patches favouring a single 'type' of change
per patch, even more so than usual with code changes. By doing so I
hope reviewers are able to parse the diff without having to think too
much. I also try to state in the commit logs if a patch makes extra
trivial changes to further ease the review process. There are however a
couple of patches here that make considerable changes to VFS files
(particularly include/linux/fs.h and include/linux/dcache.h); these will
likely require a little more attention when reviewing please, there are 3:

vfs: Clean up VFS data structure declarations

Adds function names to VFS ops methods (i.e. sturct members that are
function pointers).

fs: Copy documentation to struct declarations
dcache: Copy documentation to struct declaration

Along with the final patch these two patches make up the meat of this
series. They add docstring comments to the core VFS data structures
declared in the headers mentioned above. The docs used are based on
those currently present in vfs.txt if available or collected by reading
the source code. Unfortunately various members remain undocumented (and
marked TODO). I am new to the VFS, I lent towards leaving a 'TODO'
rather than writing wrong/vague documentation.

Of note also is that Sphinx doesn't currently really support documenting
'methods'. The docs added in this series parse (in my opinion)
reasonable well in both text and HTML. The layout is however very
slightly different from other places in the kernel documentation. I
have CC'd Jon (for obvious reasons) and Jani (because of previous
discussion on this topic on LKML) on the relevant patches.

This version is considerably different to v2 because it was not
until after posting that I realised that we could put the docs in the
header files along with the struct declarations. The justification for
doing so is that documentation far away from source code tends to go
stale, currently the vfs.txt documents core VFS data structures with
some references as old as v2.6 kernel.


Patch 1 - fs.h preparation
Patch 2 - Adds some parameter names to ops struct methods and fixes
whitespace issues withthe struct declarations.
Patch 3-7 - Fix Sphinx warnings in preparation for working on VFS docs.
Patch 8 - dcache.[ch] preparation.
Patch 9-10 - Minor grammar fixes.
Patch 11 - Cleans up docstring for d_drop(), __d_drop(), and ___d_drop().
Patch 12 - Does [minor] comment clean up in non-docstring comments.
Patch 13 - Improves the docstrings for the dcache.

I recently posted an RFC set attempting to make slab objects movable,
hopefully we can use this to make slab dentry objects movable. This
series was motivated by trying to grok the dcache in an attempt to do
so.

Patch 14 - Does (possibly anal) cleanup of docstring function
parameters. Done as a separate patch to reduce the thought
required to review the previous patch. Should, hopefully, be
trivial to review.
Patch 15-21 - Does preparatory fixes to vfs.txt ready for RST conversion,
these are as they were in v2 including tested-by tag from
Randy.
Patch 22 - As mentioned above, adds docstring documentation to the
core VFS data structure struct declarations in fs.h
Patch 23 - Does the same for struct dentry declaration in dcache.h
Patch 24 - Does the actual reStructuredText conversion.

Building on top of Mauro's work updating
Documentation/filesystems/index.rst this includes the new vfs.rst at the
top of the current index.rst. This is justified since vfs.rst is an
overview of the VFS. This does however mean that some types are
included in the rst doc books more than once.

I got a little confused by the iopoll() method of file_operations while
checking this series against different trees. If I got it right, iopoll
is _gone_ from the VFS tree so it is _not_ in this set.


Thanks for taking the time to read this.

Tobin


Changes since v2:
- Rebased onto Al's VFS tree
- Fix Sphinx warnings for fs (these were done against the tip of docs
tree before rebasing on the VFS tree).
- Clean up dcache docstrings
- Add docstrings to struct declarations (include/linux[fs.h,dcache.h])

Changes since v1:

- Re-base onto commit 9834857754ff ("doc:it_IT: translations for documents in process/")
- Add 'Tested-by:' tag for Randy (thanks!)


Tobin C. Harding (24):
vfs: Remove trailing whitespace
vfs: Clean up VFS data structure declarations
fs: Update function docstring for dio_complete()
fs: Add docstrings to exported functions
fs: Guard unusual text with backticks
fs: Update function docstring for simple_write_end()
fs: Fix function docstring for posix_acl_update_mode()
dcache: Remove trailing whitespace
dcache: Fix i.e. usage in coments
dcache: Fix e.g. usage in comment
dcache: Fix docstring comment for d_drop()
dcache: Fix non-docstring comments
dcache: Clean up function docstrings
dcache: Clean up function docstring members
docs: filesystems: vfs: Remove space before tab
docs: filesystems: vfs: Use uniform space after period.
docs: filesystems: vfs: Use 72 character column width
docs: filesystems: vfs: Use uniform spacing around headings
docs: filesystems: vfs: Use correct initial heading
docs: filesystems: vfs: Use SPDX identifier
docs: filesystems: vfs: Fix pre-amble indentation
fs: Copy documentation to struct declarations
dcache: Copy documentation to struct declaration
docs: Convert vfs.txt to reStructuredText format

Documentation/filesystems/index.rst | 6 +
Documentation/filesystems/porting | 10 +-
Documentation/filesystems/vfs.rst | 426 ++++++++++++
Documentation/filesystems/vfs.txt | 502 +++++++-------
fs/dcache.c | 469 +++++++------
fs/direct-io.c | 4 +-
fs/file_table.c | 23 +-
fs/libfs.c | 27 +-
fs/posix_acl.c | 16 +-
include/linux/dcache.h | 272 ++++++--
include/linux/fs.h | 993 +++++++++++++++++++++++++---
11 files changed, 2112 insertions(+), 636 deletions(-)
create mode 100644 Documentation/filesystems/vfs.rst

--
2.21.0



2019-03-27 05:19:24

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 01/24] vfs: Remove trailing whitespace

Currently there are a few instances of trailing whitespace. In
preparation for patching fs.h lets remove them.

Remove trailing whitespace.

Signed-off-by: Tobin C. Harding <[email protected]>
---
include/linux/fs.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 3e85cb8e8c20..4f9d2e6b9ac3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -239,7 +239,7 @@ struct iattr {
*/
#define FILESYSTEM_MAX_STACK_DEPTH 2

-/**
+/**
* enum positive_aop_returns - aop return codes with specific semantics
*
* @AOP_WRITEPAGE_ACTIVATE: Informs the caller that page writeback has
@@ -249,7 +249,7 @@ struct iattr {
* be a candidate for writeback again in the near
* future. Other callers must be careful to unlock
* the page if they get this return. Returned by
- * writepage();
+ * writepage();
*
* @AOP_TRUNCATED_PAGE: The AOP method that was handed a locked page has
* unlocked it and the page might have been truncated.
@@ -959,8 +959,8 @@ static inline struct file *get_file(struct file *f)

#define MAX_NON_LFS ((1UL<<31) - 1)

-/* Page cache limit. The filesystems should put that into their s_maxbytes
- limits, otherwise bad things can happen in VM. */
+/* Page cache limit. The filesystems should put that into their s_maxbytes
+ limits, otherwise bad things can happen in VM. */
#if BITS_PER_LONG==32
#define MAX_LFS_FILESIZE ((loff_t)ULONG_MAX << PAGE_SHIFT)
#elif BITS_PER_LONG==64
@@ -2170,7 +2170,7 @@ int sync_inode_metadata(struct inode *inode, int wait);
struct file_system_type {
const char *name;
int fs_flags;
-#define FS_REQUIRES_DEV 1
+#define FS_REQUIRES_DEV 1
#define FS_BINARY_MOUNTDATA 2
#define FS_HAS_SUBTYPE 4
#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
@@ -2938,7 +2938,7 @@ extern ssize_t kernel_read(struct file *, void *, size_t, loff_t *);
extern ssize_t kernel_write(struct file *, const void *, size_t, loff_t *);
extern ssize_t __kernel_write(struct file *, const void *, size_t, loff_t *);
extern struct file * open_exec(const char *);
-
+
/* fs/dcache.c -- generic fs support functions */
extern bool is_subdir(struct dentry *, struct dentry *);
extern bool path_is_under(const struct path *, const struct path *);
--
2.21.0


2019-03-27 05:19:32

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 02/24] vfs: Clean up VFS data structure declarations

VFS core data structure declarations are included in the documentation
as is. In preparation for updating the VFS documentation we can tidy
them up a wee bit. Many have no named parameters, for types such as
'char *' and 'int' this is not descriptive. We can do better by
including parameter names for such data types. Adding names to
parameters that are obvious (such as `struct dentry *`) does not add any
extra clarity to the code so increases the line length unnecessarily,
leave these un-named.

The only other issues are whitespace. Some methods use whitespace
before the parameters and some don't, whichever we use we should be
uniform, follow checkpatch suggestion and do not use whitespace between
function pointer identifier and the parameter list, for example:

int (*foo)(int arg)

Clean up structs by adding parameter names when useful and fixing
whitespace usage within struct definitions to be uniform across the
file.

Signed-off-by: Tobin C. Harding <[email protected]>
---
include/linux/fs.h | 181 ++++++++++++++++++++++++---------------------
1 file changed, 97 insertions(+), 84 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4f9d2e6b9ac3..a8af48d3bd4f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -356,38 +356,40 @@ struct address_space_operations {
* PURELY used for read-ahead!.
*/
int (*readpages)(struct file *filp, struct address_space *mapping,
- struct list_head *pages, unsigned nr_pages);
+ struct list_head *pages, unsigned nr_pages);

int (*write_begin)(struct file *, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata);
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
int (*write_end)(struct file *, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata);
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata);

/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
sector_t (*bmap)(struct address_space *, sector_t);
- void (*invalidatepage) (struct page *, unsigned int, unsigned int);
- int (*releasepage) (struct page *, gfp_t);
+ void (*invalidatepage)(struct page *, unsigned int offset,
+ unsigned int length);
+ int (*releasepage)(struct page *, gfp_t);
void (*freepage)(struct page *);
ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
/*
* migrate the contents of a page to the specified target. If
* migrate_mode is MIGRATE_ASYNC, it must not block.
*/
- int (*migratepage) (struct address_space *,
- struct page *, struct page *, enum migrate_mode);
+ int (*migratepage)(struct address_space *mapping,
+ struct page *newpage, struct page *page,
+ enum migrate_mode mode);
bool (*isolate_page)(struct page *, isolate_mode_t);
void (*putback_page)(struct page *);
- int (*launder_page) (struct page *);
- int (*is_partially_uptodate) (struct page *, unsigned long,
- unsigned long);
- void (*is_dirty_writeback) (struct page *, bool *, bool *);
+ int (*launder_page)(struct page *);
+ int (*is_partially_uptodate)(struct page *, unsigned long from,
+ unsigned long count);
+ void (*is_dirty_writeback)(struct page *, bool *dirty, bool *writeback);
int (*error_remove_page)(struct address_space *, struct page *);

/* swapfile support */
int (*swap_activate)(struct swap_info_struct *sis, struct file *file,
- sector_t *span);
+ sector_t *span);
void (*swap_deactivate)(struct file *file);
};

@@ -1784,73 +1786,82 @@ struct iov_iter;

struct file_operations {
struct module *owner;
- loff_t (*llseek) (struct file *, loff_t, int);
- ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
- ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
- ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
- ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
- int (*iterate) (struct file *, struct dir_context *);
- int (*iterate_shared) (struct file *, struct dir_context *);
- __poll_t (*poll) (struct file *, struct poll_table_struct *);
- long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
- long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
- int (*mmap) (struct file *, struct vm_area_struct *);
+ loff_t (*llseek)(struct file *, loff_t, int whence);
+ ssize_t (*read)(struct file *, char __user *buf, size_t bufsz,
+ loff_t *ppos);
+ ssize_t (*write)(struct file *, const char __user *buf, size_t bufsz,
+ loff_t *ppos);
+ ssize_t (*read_iter)(struct kiocb *, struct iov_iter *);
+ ssize_t (*write_iter)(struct kiocb *, struct iov_iter *);
+ int (*iterate)(struct file *, struct dir_context *);
+ int (*iterate_shared)(struct file *, struct dir_context *);
+ __poll_t (*poll)(struct file *, struct poll_table_struct *);
+ long (*unlocked_ioctl)(struct file *, unsigned int cmd, unsigned long arg);
+ long (*compat_ioctl)(struct file *, unsigned int cmd, unsigned long arg);
+ int (*mmap)(struct file *, struct vm_area_struct *);
unsigned long mmap_supported_flags;
- int (*open) (struct inode *, struct file *);
- int (*flush) (struct file *, fl_owner_t id);
- int (*release) (struct inode *, struct file *);
- int (*fsync) (struct file *, loff_t, loff_t, int datasync);
- int (*fasync) (int, struct file *, int);
- int (*lock) (struct file *, int, struct file_lock *);
- ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
- unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
- int (*check_flags)(int);
- int (*flock) (struct file *, int, struct file_lock *);
- ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
- ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
- int (*setlease)(struct file *, long, struct file_lock **, void **);
- long (*fallocate)(struct file *file, int mode, loff_t offset,
- loff_t len);
+ int (*open)(struct inode *, struct file *);
+ int (*flush)(struct file *, fl_owner_t id);
+ int (*release)(struct inode *, struct file *);
+ int (*fsync)(struct file *, loff_t start, loff_t end, int datasync);
+ int (*fasync)(int fd, struct file *, int flags);
+ int (*lock)(struct file *, int cmd, struct file_lock *);
+ ssize_t (*sendpage)(struct file *, struct page *, int, size_t, loff_t *, int);
+ unsigned long (*get_unmapped_area)(struct file *, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags);
+ int (*check_flags)(int flags);
+ int (*flock)(struct file *, int cmd, struct file_lock *);
+ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *,
+ size_t len, unsigned int flags);
+ ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *,
+ size_t len, unsigned int flags);
+ int (*setlease)(struct file *, long arg, struct file_lock **, void **priv);
+ long (*fallocate)(struct file *, int mode, loff_t offset, loff_t len);
void (*show_fdinfo)(struct seq_file *m, struct file *f);
#ifndef CONFIG_MMU
unsigned (*mmap_capabilities)(struct file *);
#endif
- ssize_t (*copy_file_range)(struct file *, loff_t, struct file *,
- loff_t, size_t, unsigned int);
+ ssize_t (*copy_file_range)(struct file *file_in, loff_t pos_in,
+ struct file *file_out, loff_t pos_out,
+ size_t len, unsigned int copy_flags);
loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
loff_t len, unsigned int remap_flags);
- int (*fadvise)(struct file *, loff_t, loff_t, int);
+ int (*fadvise)(struct file *, loff_t offset, loff_t len, int advice);
} __randomize_layout;

struct inode_operations {
- struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
- const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *);
- int (*permission) (struct inode *, int);
- struct posix_acl * (*get_acl)(struct inode *, int);
-
- int (*readlink) (struct dentry *, char __user *,int);
-
- int (*create) (struct inode *,struct dentry *, umode_t, bool);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
- int (*mkdir) (struct inode *,struct dentry *,umode_t);
- int (*rmdir) (struct inode *,struct dentry *);
- int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
- int (*rename) (struct inode *, struct dentry *,
- struct inode *, struct dentry *, unsigned int);
- int (*setattr) (struct dentry *, struct iattr *);
- int (*getattr) (const struct path *, struct kstat *, u32, unsigned int);
- ssize_t (*listxattr) (struct dentry *, char *, size_t);
+ struct dentry * (*lookup)(struct inode *dir, struct dentry *dentry,
+ unsigned int flags);
+ const char * (*get_link)(struct dentry *, struct inode *, struct delayed_call *);
+ int (*permission)(struct inode *, int mask);
+ struct posix_acl * (*get_acl)(struct inode *inode, int type);
+
+ int (*readlink)(struct dentry *, char __user *buf, int bufsz);
+
+ int (*create)(struct inode *, struct dentry *, umode_t, bool);
+ int (*link)(struct dentry *, struct inode *, struct dentry *);
+ int (*unlink)(struct inode *, struct dentry *);
+ int (*symlink)(struct inode *, struct dentry *, const char *symname);
+ int (*mkdir)(struct inode *, struct dentry *, umode_t);
+ int (*rmdir)(struct inode *, struct dentry *);
+ int (*mknod)(struct inode *, struct dentry *, umode_t, dev_t);
+ int (*rename)(struct inode *old_inode, struct dentry *old_dentry,
+ struct inode *new_inode, struct dentry *new_dentry,
+ unsigned int flags);
+ int (*setattr)(struct dentry *, struct iattr *);
+ int (*getattr)(const struct path *, struct kstat *,
+ u32 request_mask, unsigned int flags);
+ ssize_t (*listxattr)(struct dentry *, char *buf, size_t bufsz);
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
u64 len);
- int (*update_time)(struct inode *, struct timespec64 *, int);
+ int (*update_time)(struct inode *, struct timespec64 *, int flags);
int (*atomic_open)(struct inode *, struct dentry *,
struct file *, unsigned open_flag,
umode_t create_mode);
- int (*tmpfile) (struct inode *, struct dentry *, umode_t);
- int (*set_acl)(struct inode *, struct posix_acl *, int);
+ int (*tmpfile)(struct inode *, struct dentry *, umode_t);
+ int (*set_acl)(struct inode *, struct posix_acl *, int type);
} ____cacheline_aligned;

static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio,
@@ -1900,30 +1911,32 @@ extern loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos,


struct super_operations {
- struct inode *(*alloc_inode)(struct super_block *sb);
+ struct inode *(*alloc_inode)(struct super_block *sb);
void (*destroy_inode)(struct inode *);

- void (*dirty_inode) (struct inode *, int flags);
- int (*write_inode) (struct inode *, struct writeback_control *wbc);
- int (*drop_inode) (struct inode *);
- void (*evict_inode) (struct inode *);
- void (*put_super) (struct super_block *);
+ void (*dirty_inode)(struct inode *, int flags);
+ int (*write_inode)(struct inode *, struct writeback_control *wbc);
+ int (*drop_inode)(struct inode *);
+ void (*evict_inode)(struct inode *);
+ void (*put_super)(struct super_block *);
int (*sync_fs)(struct super_block *sb, int wait);
- int (*freeze_super) (struct super_block *);
- int (*freeze_fs) (struct super_block *);
- int (*thaw_super) (struct super_block *);
- int (*unfreeze_fs) (struct super_block *);
- int (*statfs) (struct dentry *, struct kstatfs *);
- int (*remount_fs) (struct super_block *, int *, char *);
- void (*umount_begin) (struct super_block *);
+ int (*freeze_super)(struct super_block *);
+ int (*freeze_fs)(struct super_block *);
+ int (*thaw_super)(struct super_block *);
+ int (*unfreeze_fs)(struct super_block *);
+ int (*statfs)(struct dentry *, struct kstatfs *);
+ int (*remount_fs)(struct super_block *, int *flags, char *options);
+ void (*umount_begin)(struct super_block *);

int (*show_options)(struct seq_file *, struct dentry *);
int (*show_devname)(struct seq_file *, struct dentry *);
int (*show_path)(struct seq_file *, struct dentry *);
int (*show_stats)(struct seq_file *, struct dentry *);
#ifdef CONFIG_QUOTA
- ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
- ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+ ssize_t (*quota_read)(struct super_block *sb, int type, char *data,
+ size_t len, loff_t off);
+ ssize_t (*quota_write)(struct super_block *sb, int type,
+ const char *data, size_t len, loff_t off);
struct dquot **(*get_dquots)(struct inode *);
#endif
int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
@@ -2177,11 +2190,11 @@ struct file_system_type {
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
int (*init_fs_context)(struct fs_context *);
const struct fs_parameter_description *parameters;
- struct dentry *(*mount) (struct file_system_type *, int,
- const char *, void *);
- void (*kill_sb) (struct super_block *);
+ struct dentry *(*mount)(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data);
+ void (*kill_sb)(struct super_block *);
struct module *owner;
- struct file_system_type * next;
+ struct file_system_type *next;
struct hlist_head fs_supers;

struct lock_class_key s_lock_key;
--
2.21.0


2019-03-27 05:19:37

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 03/24] fs: Update function docstring for dio_complete()

Sphinx throws a warning when parsing fs/direct_io.c, the warning
illuminates the fact that the docstring for function dio_complete() has
become stale.

Update the function docstring for dio_complete() documenting all current
function parameters.

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/direct-io.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/fs/direct-io.c b/fs/direct-io.c
index dbc1a1f080ce..ce5fd5f8603c 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -242,7 +242,9 @@ void dio_warn_stale_pagecache(struct file *filp)

/**
* dio_complete() - called when all DIO BIO I/O has been completed
- * @offset: the byte offset in the file of the completed operation
+ * @dio: The dio we are working on.
+ * @ret: Error code passed through from do_blockdev_direct_IO().
+ * @flags: DIO complete flags.
*
* This drops i_dio_count, lets interested parties know that a DIO operation
* has completed, and calculates the resulting return code for the operation.
--
2.21.0


2019-03-27 05:19:41

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 04/24] fs: Add docstrings to exported functions

Currently exported docstrings for fs/file_table.c are included in
Documentation/filesystems/api-summary.rst. This is a problem because
there are no docstrings in file_table.c

Add function docstrings for exported functions defined in
fs/file_table.c

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/file_table.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/fs/file_table.c b/fs/file_table.c
index 5679e7fcb6b0..e3c6966c2d53 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -65,8 +65,8 @@ static long get_nr_files(void)
return percpu_counter_read_positive(&nr_files);
}

-/*
- * Return the maximum number of open files in the system
+/**
+ * get_max_files() - Get the maximum number of open files in the system.
*/
unsigned long get_max_files(void)
{
@@ -178,8 +178,7 @@ struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred)
}

/**
- * alloc_file - allocate and initialize a 'struct file'
- *
+ * alloc_file() - Allocate and initialize a &struct file.
* @path: the (dentry, vfsmount) pair for the new file
* @flags: O_... flags with which the new file will be opened
* @fop: the 'struct file_operations' for the new file
@@ -210,6 +209,20 @@ static struct file *alloc_file(const struct path *path, int flags,
return file;
}

+/**
+ * alloc_file_pseudo() - Allocate a pseudo file.
+ * @inode: The inode to fill in.
+ * @mnt: The vfsmount to use.
+ * @name: Name to used for newly allocated pseudo dentry.
+ * @flags: ``O_...`` flags with which the new file will be opened.
+ * @fops: fops for the new file.
+ *
+ * Allocate a pseudo dentry, fill in @inode information in the dentry
+ * (i.e. instantiate @inode). Create a &struct path from the dentry and
+ * @mnt. Allocate a &struct file from the newly created path.
+ *
+ * Return: The newly allocated file or -ENOMEM on error.
+ */
struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
const char *name, int flags,
const struct file_operations *fops)
--
2.21.0


2019-03-27 05:19:50

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 05/24] fs: Guard unusual text with backticks

Currently we have unusual text which in context is clear

@flags: O_... flags with which the new file will be opened

Currently this docstring is _not_ included in any documentation file but
if it is in future this will cause Sphinx to emit a warning (as
discovered while documenting alloc_file_pseudo()). Let's fix it now to
save our future selves the hassle.

Guard unusual text with backticks.

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/file_table.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/file_table.c b/fs/file_table.c
index e3c6966c2d53..89875f1a1195 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -180,7 +180,7 @@ struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred)
/**
* alloc_file() - Allocate and initialize a &struct file.
* @path: the (dentry, vfsmount) pair for the new file
- * @flags: O_... flags with which the new file will be opened
+ * @flags: ``O_...`` flags with which the new file will be opened
* @fop: the 'struct file_operations' for the new file
*/
static struct file *alloc_file(const struct path *path, int flags,
--
2.21.0


2019-03-27 05:19:56

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 06/24] fs: Update function docstring for simple_write_end()

Shinx emits a warning due to an extra function parameter in the current
function docstring for simple_write_end(). While we are fixing this
warning we might as well clean up the whole function docstring for this
function.

The current member descriptions are readable in text and also ok in
HTML. When vfs.txt is converted to use RST format these member
descriptions could be improved with a reference to struct
address_space_operations docs in that file.

Update and cleanup docstring for simple_write_end()

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/libfs.c | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/fs/libfs.c b/fs/libfs.c
index 0fb590d79f30..36af25b9b2a3 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -448,9 +448,8 @@ int simple_write_begin(struct file *file, struct address_space *mapping,
EXPORT_SYMBOL(simple_write_begin);

/**
- * simple_write_end - .write_end helper for non-block-device FSes
- * @available: See .write_end of address_space_operations
- * @file: "
+ * simple_write_end() - .write_end helper for non-block-device FSes
+ * @file: See .write_end of &struct address_space_operations
* @mapping: "
* @pos: "
* @len: "
@@ -458,17 +457,21 @@ EXPORT_SYMBOL(simple_write_begin);
* @page: "
* @fsdata: "
*
- * simple_write_end does the minimum needed for updating a page after writing is
- * done. It has the same API signature as the .write_end of
- * address_space_operations vector. So it can just be set onto .write_end for
- * FSes that don't need any other processing. i_mutex is assumed to be held.
- * Block based filesystems should use generic_write_end().
- * NOTE: Even though i_size might get updated by this function, mark_inode_dirty
- * is not called, so a filesystem that actually does store data in .write_inode
- * should extend on what's done here with a call to mark_inode_dirty() in the
- * case that i_size has changed.
+ * Does the minimum needed for updating a page after writing is done.
+ * It has the same API signature as the .write_end member of &struct
+ * address_space_operations vector. So it can just be set onto
+ * .write_end for FSes that don't need any other processing. Block
+ * based filesystems should use generic_write_end().
+ *
+ * NOTE: Even though i_size might get updated by this function,
+ * mark_inode_dirty() is not called, so a filesystem that actually does
+ * store data in .write_inode should extend on what's done here with a
+ * call to mark_inode_dirty() in the case that i_size has changed.
*
* Use *ONLY* with simple_readpage()
+ *
+ * Context: Caller must hold i_mutex
+ * Return: @copied argument unmodified.
*/
int simple_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
--
2.21.0


2019-03-27 05:20:04

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 07/24] fs: Fix function docstring for posix_acl_update_mode()

Sphinx emits a bunch of warnings due to undocumented function parameters
for posix_acl_update_mode(). We should document all the parameters.

Docstring is currently stale in places, it references a non-existent
function, inode_change_ok(). As noted in the documentation file
Documentation/filesystems/Porting this function is now called
setattr_prepare().

Currently docstring includes 'setgit bit', meaning is not totally
clear (to me), setattr_prepare() uses term 'SGID bit', let's use this
too.

Fix function docstring for posix_acl_update_mode():

- Document function parameters.
- Reference setattr_prepare() instead of inode_change_ok().
- Use 'SGID bit' instead of 'setgit bit'.

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/posix_acl.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 2fd0fde16fe1..07394510c3d6 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -629,14 +629,18 @@ posix_acl_create(struct inode *dir, umode_t *mode,
EXPORT_SYMBOL_GPL(posix_acl_create);

/**
- * posix_acl_update_mode - update mode in set_acl
+ * posix_acl_update_mode() - Update mode in set_acl.
+ * @inode: The inode we are working on.
+ * @mode_p: New mode to use when updating.
+ * @acl: ACL we are operating on.
*
- * Update the file mode when setting an ACL: compute the new file permission
- * bits based on the ACL. In addition, if the ACL is equivalent to the new
- * file mode, set *acl to NULL to indicate that no ACL should be set.
+ * Update the file mode when setting an ACL, compute the new file
+ * permission bits based on the ACL. In addition, if the ACL is
+ * equivalent to the new file mode, set ``*acl`` to %NULL to indicate
+ * that no ACL should be set.
*
- * As with chmod, clear the setgit bit if the caller is not in the owning group
- * or capable of CAP_FSETID (see inode_change_ok).
+ * As with chmod, clear the SGID bit if the caller is not in the owning
+ * group or capable of CAP_FSETID (see setattr_prepare()).
*
* Called from set_acl inode operations.
*/
--
2.21.0


2019-03-27 05:20:12

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 08/24] dcache: Remove trailing whitespace

File contains various instances of trailing whitespace. As initial stage
of working on dcache lets clean up the trailing whitespace.

Remove trailing whitespace.

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/dcache.c | 26 +++++++++++++-------------
include/linux/dcache.h | 6 +++---
2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 2593153471cf..7bc7cf9b8962 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -254,7 +254,7 @@ static void __d_free(struct rcu_head *head)
{
struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);

- kmem_cache_free(dentry_cache, dentry);
+ kmem_cache_free(dentry_cache, dentry);
}

static void __d_free_external(struct rcu_head *head)
@@ -784,7 +784,7 @@ static inline bool fast_dput(struct dentry *dentry)
}


-/*
+/*
* This is dput
*
* This is complicated by the fact that we do not want to put
@@ -803,7 +803,7 @@ static inline bool fast_dput(struct dentry *dentry)

/*
* dput - release a dentry
- * @dentry: dentry to release
+ * @dentry: dentry to release
*
* Release a dentry. This will drop the usage count and if appropriate
* call the dentry unlink method as well as removing it from the queues and
@@ -1589,7 +1589,7 @@ EXPORT_SYMBOL(d_invalidate);
* available. On a success the dentry is returned. The name passed in is
* copied and the copy passed in may be reused after this call.
*/
-
+
struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
{
struct dentry *dentry;
@@ -1616,14 +1616,14 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
GFP_KERNEL_ACCOUNT |
__GFP_RECLAIMABLE);
if (!p) {
- kmem_cache_free(dentry_cache, dentry);
+ kmem_cache_free(dentry_cache, dentry);
return NULL;
}
atomic_set(&p->u.count, 1);
dname = p->name;
} else {
dname = dentry->d_iname;
- }
+ }

dentry->d_name.len = name->len;
dentry->d_name.hash = name->hash;
@@ -1842,7 +1842,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
* (or otherwise set) by the caller to indicate that it is now
* in use by the dcache.
*/
-
+
void d_instantiate(struct dentry *entry, struct inode * inode)
{
BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
@@ -2054,7 +2054,7 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
if (!found) {
iput(inode);
return ERR_PTR(-ENOMEM);
- }
+ }
}
res = d_splice_alias(inode, found);
if (res) {
@@ -2263,7 +2263,7 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
* See Documentation/filesystems/path-lookup.txt for more details.
*/
rcu_read_lock();
-
+
hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {

if (dentry->d_name.hash != hash)
@@ -2326,7 +2326,7 @@ EXPORT_SYMBOL(d_hash_and_lookup);
* it from the hash queues and waiting for
* it to be deleted later when it has no users
*/
-
+
/**
* d_delete - delete a dentry
* @dentry: The dentry to delete
@@ -2334,7 +2334,7 @@ EXPORT_SYMBOL(d_hash_and_lookup);
* Turn the dentry into a negative dentry if possible, otherwise
* remove it from the hash queues so it can be deleted later
*/
-
+
void d_delete(struct dentry * dentry)
{
struct inode *inode = dentry->d_inode;
@@ -2372,7 +2372,7 @@ static void __d_rehash(struct dentry *entry)
*
* Adds a dentry to the hash according to its name.
*/
-
+
void d_rehash(struct dentry * entry)
{
spin_lock(&entry->d_lock);
@@ -2964,7 +2964,7 @@ EXPORT_SYMBOL(d_splice_alias);
* Returns false otherwise.
* Caller must ensure that "new_dentry" is pinned before calling is_subdir()
*/
-
+
bool is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
{
bool result;
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index ef4b70f64f33..2fc9fc59adb1 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -266,7 +266,7 @@ extern int path_has_submounts(const struct path *);
* This adds the entry to the hash queues.
*/
extern void d_rehash(struct dentry *);
-
+
extern void d_add(struct dentry *, struct inode *);

/* used for rename() and baskets */
@@ -306,7 +306,7 @@ extern char *dentry_path(struct dentry *, char *, int);
* @dentry: dentry to get a reference to
*
* Given a dentry or %NULL pointer increment the reference count
- * if appropriate and return the dentry. A dentry will not be
+ * if appropriate and return the dentry. A dentry will not be
* destroyed when it has references.
*/
static inline struct dentry *dget_dlock(struct dentry *dentry)
@@ -331,7 +331,7 @@ extern struct dentry *dget_parent(struct dentry *dentry);
*
* Returns true if the dentry passed is not currently hashed.
*/
-
+
static inline int d_unhashed(const struct dentry *dentry)
{
return hlist_bl_unhashed(&dentry->d_hash);
--
2.21.0


2019-03-27 05:20:21

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 09/24] dcache: Fix i.e. usage in coments

The correct abbreviation for 'id est' or 'in other words' is 'i.e.' not
'ie'.

Use correct short form: i.e.

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/dcache.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 7bc7cf9b8962..9fc13c574bfb 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -366,7 +366,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
* LRU list _and_ the DCACHE_SHRINK_LIST use.
*
* The DCACHE_SHRINK_LIST bit is set whenever the dentry is
- * on the shrink list (ie not on the superblock LRU list).
+ * on the shrink list (i.e. not on the superblock LRU list).
*
* The per-cpu "nr_dentry_unused" counters are updated with
* the DCACHE_LRU_LIST bit.
@@ -408,7 +408,7 @@ static void d_shrink_add(struct dentry *dentry, struct list_head *list)
}

/*
- * These can only be called under the global LRU lock, ie during the
+ * These can only be called under the global LRU lock, i.e. during the
* callback for freeing the LRU list. "isolate" removes it from the
* LRU lists entirely, while shrink_move moves it to the indicated
* private list.
--
2.21.0


2019-03-27 05:20:44

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 14/24] dcache: Clean up function docstring members

We just cleaned up the function docstrings, we omitted while doing that
clean up the member descriptions. This was done to ease the cognitive
load required for review. Seeing what has changed in a line with an
added period can be taxing on the patch reader, if we do all these
changes as a separate patch its easier to review.

Clean up function docstring member descriptions:n
- Capitalise the initial character.
- Add period (full stop) to end of string.
- iff required flesh out the description.

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/dcache.c | 90 ++++++++++++++++++++++++++---------------------------
1 file changed, 45 insertions(+), 45 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 7acf94290b66..4ed26a7e0ec8 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -814,7 +814,7 @@ static inline bool fast_dput(struct dentry *dentry)

/**
* dput() - Release a dentry.
- * @dentry: dentry to release
+ * @dentry: The dentry to release.
*
* Release a dentry. This will drop the usage count and if appropriate
* call the dentry unlink method as well as removing it from the queues and
@@ -910,7 +910,7 @@ static struct dentry * __d_find_any_alias(struct inode *inode)

/**
* d_find_any_alias() - Find any alias for a given inode.
- * @inode: inode to find an alias for
+ * @inode: The inode to find an alias for.
*
* If any aliases exist for the given inode, take and return a
* reference for one of them.
@@ -949,7 +949,7 @@ static struct dentry *__d_find_alias(struct inode *inode)

/**
* d_find_alias() - Grab a hashed alias of inode.
- * @inode: inode in question
+ * @inode: The inode in question.
*
* If inode has a hashed alias, or is a directory and has any alias,
* acquire the reference to alias. Notice that if inode is a directory
@@ -1156,7 +1156,7 @@ static enum lru_status dentry_lru_isolate(struct list_head *item,

/**
* prune_dcache_sb() - Shrink the dcache.
- * @sb: superblock
+ * @sb: The superblock to shrink.
* @sc: shrink control, passed to list_lru_shrink_walk()
*
* Attempt to shrink the superblock dcache LRU by @sc->nr_to_scan entries. This
@@ -1372,7 +1372,7 @@ static enum d_walk_ret path_check_mount(void *data, struct dentry *dentry)

/**
* path_has_submounts() - Check current namespace for mounts over a dentry.
- * @parent: path to check.
+ * @parent: The path to check.
*
* Return: True if the parent or its subdirectories contain
* a mount point in the current namespace.
@@ -1481,7 +1481,7 @@ static enum d_walk_ret select_collect(void *_data, struct dentry *dentry)

/**
* shrink_dcache_parent() - Prune dcache.
- * @parent: parent of entries to prune
+ * @parent: The parent of entries to prune.
*
* Prune the dcache to remove unused children of the parent dentry.
*/
@@ -1576,7 +1576,7 @@ static enum d_walk_ret find_submount(void *_data, struct dentry *dentry)

/**
* d_invalidate() - Detach submounts, prune dcache, and drop.
- * @dentry: dentry to invalidate (aka detach, prune and drop)
+ * @dentry: The dentry to invalidate (aka detach, prune and drop).
*/
void d_invalidate(struct dentry *dentry)
{
@@ -1611,8 +1611,8 @@ EXPORT_SYMBOL(d_invalidate);

/**
* __d_alloc() - Allocate a dcache entry.
- * @sb: filesystem it will belong to
- * @name: qstr of the name
+ * @sb: The filesystem it will belong to.
+ * @name: The qstr of the name.
*
* @name is copied and may be reused after this call.
*
@@ -1695,8 +1695,8 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)

/**
* d_alloc() - Allocate a dcache entry.
- * @parent: parent of entry to allocate
- * @name: qstr of the name
+ * @parent: The parent of entry to allocate.
+ * @name: The qstr of the name.
*
* Allocates a dentry and adds it to @parent. See __d_alloc() for full
* explanation of behaviour.
@@ -1743,8 +1743,8 @@ struct dentry *d_alloc_cursor(struct dentry * parent)

/**
* d_alloc_pseudo() - Allocate a dentry (for lookup-less filesystems).
- * @sb: the superblock
- * @name: qstr of the name
+ * @sb: The superblock.
+ * @name: The qstr of the name.
*
* For a filesystem that just pins its dentries in memory and never
* performs lookups at all, return an unhashed IS_ROOT dentry.
@@ -1872,8 +1872,8 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)

/**
* d_instantiate() - Fill in inode information for a dentry.
- * @entry: dentry to complete
- * @inode: inode to attach to this dentry
+ * @entry: The dentry to complete.
+ * @inode: The inode to attach to this dentry.
*
* This turns negative dentries into productive full members
* of society.
@@ -2012,7 +2012,7 @@ static struct dentry *__d_obtain_alias(struct inode *inode, bool disconnected)

/**
* d_obtain_alias() - Find or allocate a DISCONNECTED dentry.
- * @inode: inode to allocate the dentry for
+ * @inode: The inode to allocate the dentry for.
*
* Obtain a dentry for an inode resulting from NFS filehandle conversion or
* similar open by handle operations. The returned dentry may be anonymous,
@@ -2036,7 +2036,7 @@ EXPORT_SYMBOL(d_obtain_alias);

/**
* d_obtain_root() - Find or allocate a dentry for a given inode.
- * @inode: inode to allocate the dentry for
+ * @inode: The inode to allocate the dentry for.
*
* Obtain an IS_ROOT dentry for the root of a filesystem.
*
@@ -2057,9 +2057,9 @@ EXPORT_SYMBOL(d_obtain_root);

/**
* d_add_ci() - Lookup or allocate new dentry with case-exact name.
- * @inode: the inode case-insensitive lookup has found
- * @dentry: the negative dentry that was passed to the parent's lookup func
- * @name: the case-exact name to be associated with the returned dentry
+ * @inode: The inode case-insensitive lookup has found.
+ * @dentry: The negative dentry that was passed to the parent's lookup func.
+ * @name: The case-exact name to be associated with the returned dentry.
*
* This is to avoid filling the dcache with case-insensitive names to the
* same inode, only the actual correct case is stored in the dcache for
@@ -2125,9 +2125,9 @@ static inline bool d_same_name(const struct dentry *dentry,

/**
* __d_lookup_rcu() - Search for a dentry (racy, store-free).
- * @parent: parent dentry
- * @name: qstr of name we wish to find
- * @seqp: returns d_seq value at the point where the dentry was found
+ * @parent: The parent dentry.
+ * @name: The qstr of name we wish to find.
+ * @seqp: Returns d_seq value at the point where the dentry was found.
*
* __d_lookup_rcu is the dcache lookup function for rcu-walk name
* resolution (store-free path walking) design described in
@@ -2241,8 +2241,8 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,

/**
* d_lookup() - Search for a dentry.
- * @parent: parent dentry
- * @name: qstr of name we wish to find
+ * @parent: The parent dentry.
+ * @name: The qstr of name we wish to find.
*
* d_lookup() searches the children of the parent dentry for the name in
* question. If the dentry is found its reference count is incremented and the
@@ -2268,8 +2268,8 @@ EXPORT_SYMBOL(d_lookup);

/**
* __d_lookup() - Search for a dentry (racy).
- * @parent: parent dentry
- * @name: qstr of name we wish to find
+ * @parent: The parent dentry.
+ * @name: The qstr of name we wish to find.
*
* __d_lookup() is like d_lookup(), however it may (rarely) return a
* false-negative result due to unrelated rename activity.
@@ -2340,8 +2340,8 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)

/**
* d_hash_and_lookup() - Hash the qstr then search for a dentry.
- * @dir: Directory to search in
- * @name: qstr of name we wish to find
+ * @dir: Directory to search in.
+ * @name: The qstr of name we wish to find.
*
* Return: The dentry if found, %NULL on lookup failure, ERR_PTR(-error)
* on bad name.
@@ -2378,7 +2378,7 @@ EXPORT_SYMBOL(d_hash_and_lookup);

/**
* d_delete() - Delete a dentry.
- * @dentry: The dentry to delete
+ * @dentry: The dentry to delete.
*
* Turn the dentry into a negative dentry if possible, otherwise
* remove it from the hash queues so it can be deleted later.
@@ -2416,7 +2416,7 @@ static void __d_rehash(struct dentry *entry)

/**
* d_rehash() - Add an entry back to the hash.
- * @entry: dentry to add to the hash
+ * @entry: The dentry to add to the hash.
*
* Adds a dentry to the hash according to its name.
*/
@@ -2613,8 +2613,8 @@ static inline void __d_add(struct dentry *dentry, struct inode *inode)

/**
* d_add() - Add dentry to hash queues.
- * @entry: dentry to add
- * @inode: The inode to attach to this dentry
+ * @entry: The dentry to add.
+ * @inode: The inode to attach to this dentry.
*
* This adds the entry to the hash queues and initializes @inode.
* The entry was actually filled in earlier during d_alloc().
@@ -2632,8 +2632,8 @@ EXPORT_SYMBOL(d_add);

/**
* d_exact_alias() - Find and hash an exact unhashed alias.
- * @entry: dentry to add
- * @inode: The inode to go with this dentry
+ * @entry: The dentry to add.
+ * @inode: The inode to go with this dentry.
*
* Context: Parent directory should be locked.
* Return: If an unhashed dentry with the same name/parent and desired
@@ -2831,8 +2831,8 @@ static void __d_move(struct dentry *dentry, struct dentry *target,

/**
* d_move() - Move a dentry.
- * @dentry: entry to move
- * @target: new dentry
+ * @dentry: The dentry to move.
+ * @target: The new dentry.
*
* Update the dcache to reflect the move of a file name. Negative
* dcache entries should not be moved in this way.
@@ -2851,8 +2851,8 @@ EXPORT_SYMBOL(d_move);

/**
* d_exchange() - Exchange two dentries.
- * @dentry1: first dentry
- * @dentry2: second dentry
+ * @dentry1: The first dentry.
+ * @dentry2: The second dentry.
*/
void d_exchange(struct dentry *dentry1, struct dentry *dentry2)
{
@@ -2870,8 +2870,8 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2)

/**
* d_ancestor() - Search for an ancestor.
- * @p1: ancestor dentry
- * @p2: child dentry
+ * @p1: The ancestor dentry.
+ * @p2: The child dentry.
*
* Return: The ancestor dentry of p2 which is a child of p1, if p1 is
* an ancestor of p2, else %NULL.
@@ -2927,8 +2927,8 @@ static int __d_unalias(struct inode *inode,

/**
* d_splice_alias() - Splice a disconnected dentry into the tree if one exists.
- * @inode: the inode which may have a disconnected dentry
- * @dentry: a negative dentry which we want to point to the inode.
+ * @inode: The inode which may have a disconnected dentry.
+ * @dentry: A negative dentry which we want to point to the inode.
*
* If inode is a directory and has an IS_ROOT alias, then d_move() that in
* place of the given dentry and return it, else simply d_add() the inode
@@ -3007,8 +3007,8 @@ EXPORT_SYMBOL(d_splice_alias);

/**
* is_subdir - is new dentry a subdirectory of old_dentry
- * @new_dentry: new dentry
- * @old_dentry: old dentry
+ * @new_dentry: The new dentry.
+ * @old_dentry: The old dentry.
*
* Return: True if new_dentry is a subdirectory of the parent (at any
* depth). False otherwise.
--
2.21.0


2019-03-27 05:20:52

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 15/24] docs: filesystems: vfs: Remove space before tab

Currently the file has a bunch of spaces before tabspaces. This is a
nuisance when patching the file because they show up whenever we touch
these lines. Let's just fix them all now in preparation for doing the
RST conversion.

Remove spaces before tabspaces.

Tested-by: Randy Dunlap <[email protected]>
Signed-off-by: Tobin C. Harding <[email protected]>
---
Documentation/filesystems/vfs.txt | 78 +++++++++++++++----------------
1 file changed, 39 insertions(+), 39 deletions(-)

diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 8dc8e9c2913f..75b47768c806 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -136,7 +136,7 @@ struct file_system_type {
should be shut down

owner: for internal VFS use: you should initialize this to THIS_MODULE in
- most cases.
+ most cases.

next: for internal VFS use: you should initialize this to NULL

@@ -145,7 +145,7 @@ struct file_system_type {
The mount() method has the following arguments:

struct file_system_type *fs_type: describes the filesystem, partly initialized
- by the specific filesystem code
+ by the specific filesystem code

int flags: mount flags

@@ -182,12 +182,12 @@ and provides a fill_super() callback instead. The generic variants are:
mount_nodev: mount a filesystem that is not backed by a device

mount_single: mount a filesystem which shares the instance between
- all mounts
+ all mounts

A fill_super() callback implementation has the following arguments:

struct super_block *sb: the superblock structure. The callback
- must initialize this properly.
+ must initialize this properly.

void *data: arbitrary mount options, usually comes as an ASCII
string (see "Mount Options" section)
@@ -238,14 +238,14 @@ only called from a process context (i.e. not from an interrupt handler
or bottom half).

alloc_inode: this method is called by alloc_inode() to allocate memory
- for struct inode and initialize it. If this function is not
- defined, a simple 'struct inode' is allocated. Normally
- alloc_inode will be used to allocate a larger structure which
- contains a 'struct inode' embedded within it.
+ for struct inode and initialize it. If this function is not
+ defined, a simple 'struct inode' is allocated. Normally
+ alloc_inode will be used to allocate a larger structure which
+ contains a 'struct inode' embedded within it.

destroy_inode: this method is called by destroy_inode() to release
- resources allocated for struct inode. It is only required if
- ->alloc_inode was defined and simply undoes anything done by
+ resources allocated for struct inode. It is only required if
+ ->alloc_inode was defined and simply undoes anything done by
->alloc_inode.

dirty_inode: this method is called by the VFS to mark an inode dirty.
@@ -273,15 +273,15 @@ or bottom half).
(i.e. unmount). This is called with the superblock lock held

sync_fs: called when VFS is writing out all dirty data associated with
- a superblock. The second parameter indicates whether the method
+ a superblock. The second parameter indicates whether the method
should wait until the write out has been completed. Optional.

freeze_fs: called when VFS is locking a filesystem and
- forcing it into a consistent state. This method is currently
- used by the Logical Volume Manager (LVM).
+ forcing it into a consistent state. This method is currently
+ used by the Logical Volume Manager (LVM).

unfreeze_fs: called when VFS is unlocking a filesystem and making it writable
- again.
+ again.

statfs: called when the VFS needs to get filesystem statistics.

@@ -472,30 +472,30 @@ otherwise noted.
that.

permission: called by the VFS to check for access rights on a POSIX-like
- filesystem.
+ filesystem.

May be called in rcu-walk mode (mask & MAY_NOT_BLOCK). If in rcu-walk
- mode, the filesystem must check the permission without blocking or
+ mode, the filesystem must check the permission without blocking or
storing to the inode.

If a situation is encountered that rcu-walk cannot handle, return
-ECHILD and it will be called again in ref-walk mode.

setattr: called by the VFS to set attributes for a file. This method
- is called by chmod(2) and related system calls.
+ is called by chmod(2) and related system calls.

getattr: called by the VFS to get attributes of a file. This method
- is called by stat(2) and related system calls.
+ is called by stat(2) and related system calls.

listxattr: called by the VFS to list all extended attributes for a
given file. This method is called by the listxattr(2) system call.

update_time: called by the VFS to update a specific time or the i_version of
- an inode. If this is not defined the VFS will update the inode itself
- and call mark_inode_dirty_sync.
+ an inode. If this is not defined the VFS will update the inode itself
+ and call mark_inode_dirty_sync.

atomic_open: called on the last component of an open. Using this optional
- method the filesystem can look up, possibly create and open the file in
+ method the filesystem can look up, possibly create and open the file in
one atomic operation. If it wants to leave actual opening to the
caller (e.g. if the file turned out to be a symlink, device, or just
something filesystem won't do atomic open for), it may signal this by
@@ -683,13 +683,13 @@ struct address_space_operations {
that all succeeds, ->readpage will be called again.

writepages: called by the VM to write out pages associated with the
- address_space object. If wbc->sync_mode is WBC_SYNC_ALL, then
- the writeback_control will specify a range of pages that must be
- written out. If it is WBC_SYNC_NONE, then a nr_to_write is given
+ address_space object. If wbc->sync_mode is WBC_SYNC_ALL, then
+ the writeback_control will specify a range of pages that must be
+ written out. If it is WBC_SYNC_NONE, then a nr_to_write is given
and that many pages should be written if possible.
If no ->writepages is given, then mpage_writepages is used
- instead. This will choose pages from the address space that are
- tagged as DIRTY and will pass them to ->writepage.
+ instead. This will choose pages from the address space that are
+ tagged as DIRTY and will pass them to ->writepage.

set_page_dirty: called by the VM to set a page dirty.
This is particularly needed if an address space attaches
@@ -700,11 +700,11 @@ struct address_space_operations {
PAGECACHE_TAG_DIRTY tag in the radix tree.

readpages: called by the VM to read pages associated with the address_space
- object. This is essentially just a vector version of
- readpage. Instead of just one page, several pages are
- requested.
+ object. This is essentially just a vector version of
+ readpage. Instead of just one page, several pages are
+ requested.
readpages is only used for read-ahead, so read errors are
- ignored. If anything goes wrong, feel free to give up.
+ ignored. If anything goes wrong, feel free to give up.

write_begin:
Called by the generic buffered write code to ask the filesystem to
@@ -741,12 +741,12 @@ struct address_space_operations {
that were able to be copied into pagecache.

bmap: called by the VFS to map a logical block offset within object to
- physical block number. This method is used by the FIBMAP
- ioctl and for working with swap-files. To be able to swap to
- a file, the file must have a stable mapping to a block
- device. The swap system does not go through the filesystem
- but instead uses bmap to find out where the blocks in the file
- are and uses those addresses directly.
+ physical block number. This method is used by the FIBMAP
+ ioctl and for working with swap-files. To be able to swap to
+ a file, the file must have a stable mapping to a block
+ device. The swap system does not go through the filesystem
+ but instead uses bmap to find out where the blocks in the file
+ are and uses those addresses directly.

invalidatepage: If a page has PagePrivate set, then invalidatepage
will be called when part or all of the page is to be removed
@@ -806,7 +806,7 @@ struct address_space_operations {
putback_page: Called by the VM when isolated page's migration fails.

launder_page: Called before freeing a page - it writes back the dirty page. To
- prevent redirtying the page, it is kept locked during the whole
+ prevent redirtying the page, it is kept locked during the whole
operation.

is_partially_uptodate: Called by the VM when reading a file through the
@@ -914,7 +914,7 @@ otherwise noted.
unlocked_ioctl: called by the ioctl(2) system call.

compat_ioctl: called by the ioctl(2) system call when 32 bit system calls
- are used on 64 bit kernels.
+ are used on 64 bit kernels.

mmap: called by the mmap(2) system call

@@ -939,7 +939,7 @@ otherwise noted.
(non-blocking) mode is enabled for a file

lock: called by the fcntl(2) system call for F_GETLK, F_SETLK, and F_SETLKW
- commands
+ commands

get_unmapped_area: called by the mmap(2) system call

--
2.21.0


2019-03-27 05:21:04

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 17/24] docs: filesystems: vfs: Use 72 character column width

In preparation for conversion to RST format use the kernels favoured
documentation column width. If we are going to do this we might as well
do it thoroughly. Just do the paragraphs (not the indented stuff), the
rest will be done during indentation fix up patch.

This patch is whitespace only, no textual changes.

Use 72 character column width for all paragraph sections.

Tested-by: Randy Dunlap <[email protected]>
Signed-off-by: Tobin C. Harding <[email protected]>
---
Documentation/filesystems/vfs.txt | 198 +++++++++++++++---------------
1 file changed, 97 insertions(+), 101 deletions(-)

diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 62a6ad52b191..5c4d74547dd7 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -14,15 +14,14 @@
Introduction
============

-The Virtual File System (also known as the Virtual Filesystem Switch)
-is the software layer in the kernel that provides the filesystem
-interface to userspace programs. It also provides an abstraction
-within the kernel which allows different filesystem implementations to
-coexist.
+The Virtual File System (also known as the Virtual Filesystem Switch) is
+the software layer in the kernel that provides the filesystem interface
+to userspace programs. It also provides an abstraction within the
+kernel which allows different filesystem implementations to coexist.

-VFS system calls open(2), stat(2), read(2), write(2), chmod(2) and so
-on are called from a process context. Filesystem locking is described
-in the document Documentation/filesystems/Locking.
+VFS system calls open(2), stat(2), read(2), write(2), chmod(2) and so on
+are called from a process context. Filesystem locking is described in
+the document Documentation/filesystems/Locking.


Directory Entry Cache (dcache)
@@ -36,11 +35,10 @@ translate a pathname (filename) into a specific dentry. Dentries live
in RAM and are never saved to disc: they exist only for performance.

The dentry cache is meant to be a view into your entire filespace. As
-most computers cannot fit all dentries in the RAM at the same time,
-some bits of the cache are missing. In order to resolve your pathname
-into a dentry, the VFS may have to resort to creating dentries along
-the way, and then loading the inode. This is done by looking up the
-inode.
+most computers cannot fit all dentries in the RAM at the same time, some
+bits of the cache are missing. In order to resolve your pathname into a
+dentry, the VFS may have to resort to creating dentries along the way,
+and then loading the inode. This is done by looking up the inode.


The Inode Object
@@ -48,33 +46,32 @@ The Inode Object

An individual dentry usually has a pointer to an inode. Inodes are
filesystem objects such as regular files, directories, FIFOs and other
-beasts. They live either on the disc (for block device filesystems)
-or in the memory (for pseudo filesystems). Inodes that live on the
-disc are copied into the memory when required and changes to the inode
-are written back to disc. A single inode can be pointed to by multiple
+beasts. They live either on the disc (for block device filesystems) or
+in the memory (for pseudo filesystems). Inodes that live on the disc
+are copied into the memory when required and changes to the inode are
+written back to disc. A single inode can be pointed to by multiple
dentries (hard links, for example, do this).

To look up an inode requires that the VFS calls the lookup() method of
the parent directory inode. This method is installed by the specific
-filesystem implementation that the inode lives in. Once the VFS has
-the required dentry (and hence the inode), we can do all those boring
-things like open(2) the file, or stat(2) it to peek at the inode
-data. The stat(2) operation is fairly simple: once the VFS has the
-dentry, it peeks at the inode data and passes some of it back to
-userspace.
+filesystem implementation that the inode lives in. Once the VFS has the
+required dentry (and hence the inode), we can do all those boring things
+like open(2) the file, or stat(2) it to peek at the inode data. The
+stat(2) operation is fairly simple: once the VFS has the dentry, it
+peeks at the inode data and passes some of it back to userspace.


The File Object
---------------

Opening a file requires another operation: allocation of a file
-structure (this is the kernel-side implementation of file
-descriptors). The freshly allocated file structure is initialized with
-a pointer to the dentry and a set of file operation member functions.
-These are taken from the inode data. The open() file method is then
-called so the specific filesystem implementation can do its work. You
-can see that this is another switch performed by the VFS. The file
-structure is placed into the file descriptor table for the process.
+structure (this is the kernel-side implementation of file descriptors).
+The freshly allocated file structure is initialized with a pointer to
+the dentry and a set of file operation member functions. These are
+taken from the inode data. The open() file method is then called so the
+specific filesystem implementation can do its work. You can see that
+this is another switch performed by the VFS. The file structure is
+placed into the file descriptor table for the process.

Reading, writing and closing files (and other assorted VFS operations)
is done by using the userspace file descriptor to grab the appropriate
@@ -95,11 +92,12 @@ functions:
extern int unregister_filesystem(struct file_system_type *);

The passed struct file_system_type describes your filesystem. When a
-request is made to mount a filesystem onto a directory in your namespace,
-the VFS will call the appropriate mount() method for the specific
-filesystem. New vfsmount referring to the tree returned by ->mount()
-will be attached to the mountpoint, so that when pathname resolution
-reaches the mountpoint it will jump into the root of that vfsmount.
+request is made to mount a filesystem onto a directory in your
+namespace, the VFS will call the appropriate mount() method for the
+specific filesystem. New vfsmount referring to the tree returned by
+->mount() will be attached to the mountpoint, so that when pathname
+resolution reaches the mountpoint it will jump into the root of that
+vfsmount.

You can see all filesystems that are registered to the kernel in the
file /proc/filesystems.
@@ -158,21 +156,21 @@ The mount() method must return the root dentry of the tree requested by
caller. An active reference to its superblock must be grabbed and the
superblock must be locked. On failure it should return ERR_PTR(error).

-The arguments match those of mount(2) and their interpretation
-depends on filesystem type. E.g. for block filesystems, dev_name is
-interpreted as block device name, that device is opened and if it
-contains a suitable filesystem image the method creates and initializes
-struct super_block accordingly, returning its root dentry to caller.
+The arguments match those of mount(2) and their interpretation depends
+on filesystem type. E.g. for block filesystems, dev_name is interpreted
+as block device name, that device is opened and if it contains a
+suitable filesystem image the method creates and initializes struct
+super_block accordingly, returning its root dentry to caller.

->mount() may choose to return a subtree of existing filesystem - it
doesn't have to create a new one. The main result from the caller's
-point of view is a reference to dentry at the root of (sub)tree to
-be attached; creation of new superblock is a common side effect.
+point of view is a reference to dentry at the root of (sub)tree to be
+attached; creation of new superblock is a common side effect.

-The most interesting member of the superblock structure that the
-mount() method fills in is the "s_op" field. This is a pointer to
-a "struct super_operations" which describes the next level of the
-filesystem implementation.
+The most interesting member of the superblock structure that the mount()
+method fills in is the "s_op" field. This is a pointer to a "struct
+super_operations" which describes the next level of the filesystem
+implementation.

Usually, a filesystem uses one of the generic mount() implementations
and provides a fill_super() callback instead. The generic variants are:
@@ -319,16 +317,16 @@ or bottom half).
implementations will cause holdoff problems due to large scan batch
sizes.

-Whoever sets up the inode is responsible for filling in the "i_op" field. This
-is a pointer to a "struct inode_operations" which describes the methods that
-can be performed on individual inodes.
+Whoever sets up the inode is responsible for filling in the "i_op"
+field. This is a pointer to a "struct inode_operations" which describes
+the methods that can be performed on individual inodes.

struct xattr_handlers
---------------------

On filesystems that support extended attributes (xattrs), the s_xattr
-superblock field points to a NULL-terminated array of xattr handlers. Extended
-attributes are name:value pairs.
+superblock field points to a NULL-terminated array of xattr handlers.
+Extended attributes are name:value pairs.

name: Indicates that the handler matches attributes with the specified name
(such as "system.posix_acl_access"); the prefix field must be NULL.
@@ -348,9 +346,9 @@ attributes are name:value pairs.
attribute. This method is called by the the setxattr(2) and
removexattr(2) system calls.

-When none of the xattr handlers of a filesystem match the specified attribute
-name or when a filesystem doesn't support extended attributes, the various
-*xattr(2) system calls return -EOPNOTSUPP.
+When none of the xattr handlers of a filesystem match the specified
+attribute name or when a filesystem doesn't support extended attributes,
+the various *xattr(2) system calls return -EOPNOTSUPP.


The Inode Object
@@ -362,8 +360,8 @@ An inode object represents an object within the filesystem.
struct inode_operations
-----------------------

-This describes how the VFS can manipulate an inode in your
-filesystem. As of kernel 2.6.22, the following members are defined:
+This describes how the VFS can manipulate an inode in your filesystem.
+As of kernel 2.6.22, the following members are defined:

struct inode_operations {
int (*create) (struct inode *,struct dentry *, umode_t, bool);
@@ -513,42 +511,40 @@ The Address Space Object
========================

The address space object is used to group and manage pages in the page
-cache. It can be used to keep track of the pages in a file (or
-anything else) and also track the mapping of sections of the file into
-process address spaces.
+cache. It can be used to keep track of the pages in a file (or anything
+else) and also track the mapping of sections of the file into process
+address spaces.

There are a number of distinct yet related services that an
-address-space can provide. These include communicating memory
-pressure, page lookup by address, and keeping track of pages tagged as
-Dirty or Writeback.
+address-space can provide. These include communicating memory pressure,
+page lookup by address, and keeping track of pages tagged as Dirty or
+Writeback.

The first can be used independently to the others. The VM can try to
-either write dirty pages in order to clean them, or release clean
-pages in order to reuse them. To do this it can call the ->writepage
-method on dirty pages, and ->releasepage on clean pages with
-PagePrivate set. Clean pages without PagePrivate and with no external
-references will be released without notice being given to the
-address_space.
+either write dirty pages in order to clean them, or release clean pages
+in order to reuse them. To do this it can call the ->writepage method
+on dirty pages, and ->releasepage on clean pages with PagePrivate set.
+Clean pages without PagePrivate and with no external references will be
+released without notice being given to the address_space.

To achieve this functionality, pages need to be placed on an LRU with
-lru_cache_add and mark_page_active needs to be called whenever the
-page is used.
+lru_cache_add and mark_page_active needs to be called whenever the page
+is used.

Pages are normally kept in a radix tree index by ->index. This tree
-maintains information about the PG_Dirty and PG_Writeback status of
-each page, so that pages with either of these flags can be found
-quickly.
+maintains information about the PG_Dirty and PG_Writeback status of each
+page, so that pages with either of these flags can be found quickly.

The Dirty tag is primarily used by mpage_writepages - the default
->writepages method. It uses the tag to find dirty pages to call
->writepage on. If mpage_writepages is not used (i.e. the address
-provides its own ->writepages) , the PAGECACHE_TAG_DIRTY tag is
-almost unused. write_inode_now and sync_inode do use it (through
+provides its own ->writepages) , the PAGECACHE_TAG_DIRTY tag is almost
+unused. write_inode_now and sync_inode do use it (through
__sync_single_inode) to check if ->writepages has been successful in
writing out the whole address_space.

-The Writeback tag is used by filemap*wait* and sync_page* functions,
-via filemap_fdatawait_range, to wait for all writeback to complete.
+The Writeback tag is used by filemap*wait* and sync_page* functions, via
+filemap_fdatawait_range, to wait for all writeback to complete.

An address_space handler may attach extra information to a page,
typically using the 'private' field in the 'struct page'. If such
@@ -558,25 +554,24 @@ handler to deal with that data.

An address space acts as an intermediate between storage and
application. Data is read into the address space a whole page at a
-time, and provided to the application either by copying of the page,
-or by memory-mapping the page.
-Data is written into the address space by the application, and then
-written-back to storage typically in whole pages, however the
-address_space has finer control of write sizes.
+time, and provided to the application either by copying of the page, or
+by memory-mapping the page. Data is written into the address space by
+the application, and then written-back to storage typically in whole
+pages, however the address_space has finer control of write sizes.

The read process essentially only requires 'readpage'. The write
process is more complicated and uses write_begin/write_end or
-set_page_dirty to write data into the address_space, and writepage
-and writepages to writeback data to storage.
+set_page_dirty to write data into the address_space, and writepage and
+writepages to writeback data to storage.

Adding and removing pages to/from an address_space is protected by the
inode's i_mutex.

When data is written to a page, the PG_Dirty flag should be set. It
typically remains set until writepage asks for it to be written. This
-should clear PG_Dirty and set PG_Writeback. It can be actually
-written at any point after PG_Dirty is clear. Once it is known to be
-safe, PG_Writeback is cleared.
+should clear PG_Dirty and set PG_Writeback. It can be actually written
+at any point after PG_Dirty is clear. Once it is known to be safe,
+PG_Writeback is cleared.

Writeback makes use of a writeback_control structure to direct the
operations. This gives the the writepage and writepages operations some
@@ -605,9 +600,10 @@ file descriptors should get back an error is not possible.
Instead, the generic writeback error tracking infrastructure in the
kernel settles for reporting errors to fsync on all file descriptions
that were open at the time that the error occurred. In a situation with
-multiple writers, all of them will get back an error on a subsequent fsync,
-even if all of the writes done through that particular file descriptor
-succeeded (or even if there were no writes on that file descriptor at all).
+multiple writers, all of them will get back an error on a subsequent
+fsync, even if all of the writes done through that particular file
+descriptor succeeded (or even if there were no writes on that file
+descriptor at all).

Filesystems that wish to use this infrastructure should call
mapping_set_error to record the error in the address_space when it
@@ -619,8 +615,8 @@ point in the stream of errors emitted by the backing device(s).
struct address_space_operations
-------------------------------

-This describes how the VFS can manipulate mapping of a file to page cache in
-your filesystem. The following members are defined:
+This describes how the VFS can manipulate mapping of a file to page
+cache in your filesystem. The following members are defined:

struct address_space_operations {
int (*writepage)(struct page *page, struct writeback_control *wbc);
@@ -1224,8 +1220,8 @@ filesystems.
Showing options
---------------

-If a filesystem accepts mount options, it must define show_options()
-to show all the currently active options. The rules are:
+If a filesystem accepts mount options, it must define show_options() to
+show all the currently active options. The rules are:

- options MUST be shown which are not default or their values differ
from the default
@@ -1233,14 +1229,14 @@ to show all the currently active options. The rules are:
- options MAY be shown which are enabled by default or have their
default value

-Options used only internally between a mount helper and the kernel
-(such as file descriptors), or which only have an effect during the
-mounting (such as ones controlling the creation of a journal) are exempt
-from the above rules.
+Options used only internally between a mount helper and the kernel (such
+as file descriptors), or which only have an effect during the mounting
+(such as ones controlling the creation of a journal) are exempt from the
+above rules.

-The underlying reason for the above rules is to make sure, that a
-mount can be accurately replicated (e.g. umounting and mounting again)
-based on the information found in /proc/mounts.
+The underlying reason for the above rules is to make sure, that a mount
+can be accurately replicated (e.g. umounting and mounting again) based
+on the information found in /proc/mounts.

Resources
=========
--
2.21.0


2019-03-27 05:21:06

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 18/24] docs: filesystems: vfs: Use uniform spacing around headings

Currently spacing before and after headings is non-uniform. Use two
blank lines before a heading and one after the heading.

Use uniform spacing around headings.

Tested-by: Randy Dunlap <[email protected]>
Signed-off-by: Tobin C. Harding <[email protected]>
---
Documentation/filesystems/vfs.txt | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 5c4d74547dd7..b452b3fc5edc 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -321,6 +321,7 @@ Whoever sets up the inode is responsible for filling in the "i_op"
field. This is a pointer to a "struct inode_operations" which describes
the methods that can be performed on individual inodes.

+
struct xattr_handlers
---------------------

@@ -507,6 +508,7 @@ otherwise noted.
tmpfile: called in the end of O_TMPFILE open(). Optional, equivalent to
atomically creating, opening and unlinking a file in given directory.

+
The Address Space Object
========================

@@ -580,8 +582,10 @@ and the constraints under which it is being done. It is also used to
return information back to the caller about the result of a writepage or
writepages request.

+
Handling errors during writeback
--------------------------------
+
Most applications that do buffered I/O will periodically call a file
synchronization call (fsync, fdatasync, msync or sync_file_range) to
ensure that data written has made it to the backing store. When there
@@ -612,6 +616,7 @@ file->fsync operation, they should call file_check_and_advance_wb_err to
ensure that the struct file's error cursor has advanced to the correct
point in the stream of errors emitted by the backing device(s).

+
struct address_space_operations
-------------------------------

@@ -1200,9 +1205,11 @@ manipulate dentries:
and the dentry is returned. The caller must use dput()
to free the dentry when it finishes using it.

+
Mount Options
=============

+
Parsing options
---------------

@@ -1217,6 +1224,7 @@ The <linux/parser.h> header defines an API that helps parse these
options. There are plenty of examples on how to use it in existing
filesystems.

+
Showing options
---------------

@@ -1238,6 +1246,7 @@ The underlying reason for the above rules is to make sure, that a mount
can be accurately replicated (e.g. umounting and mounting again) based
on the information found in /proc/mounts.

+
Resources
=========

--
2.21.0


2019-03-27 05:21:19

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 22/24] fs: Copy documentation to struct declarations

Currently the documentation for structures declared in fs.h is located
in Documentation/filesystems/vfs.txt. Having documentation far away
from the code increases the chance of docs getting stale. This is
exactly the case with fs core data structure documentation. Docs
currently reference 2.6 kernels.

The kernel has a mechanism for documenting structures in the
source/header files, we should use it. This makes reading arguable
easier because documentation is right there with the source and also
prevent the docs from getting stale.

Copy documentation for filesystem data structures from vfs.txt and
locate it in docstrings with the struct declarations.
into fs.h

Where members are not documented, document with string:

TODO: document this

To ease review do not touch vfs.txt, this file will be converted to rst
shortly.

Cc: Jani Nikula <[email protected]>
Cc: Jonathan Corbet <[email protected]>
Signed-off-by: Tobin C. Harding <[email protected]>
---
include/linux/fs.h | 802 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 788 insertions(+), 14 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index a8af48d3bd4f..f2baf7c7e537 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -341,55 +341,264 @@ typedef struct {
typedef int (*read_actor_t)(read_descriptor_t *, struct page *,
unsigned long, unsigned long);

+/**
+ * struct address_space_operations - This describes how the VFS can manipulate
+ * mapping of a file to page cache in your filesystem.
+ */
struct address_space_operations {
+ /**
+ * @writepage: Called by the VM to write a dirty page to backing
+ * store. This may happen for data integrity reasons
+ * (i.e. 'sync'), or to free up memory (flush). The difference
+ * can be seen in wbc->sync_mode. The PG_Dirty flag has been
+ * cleared and PageLocked is true. writepage() should start
+ * writeout, should set PG_Writeback, and should make sure the
+ * page is unlocked, either synchronously or asynchronously when
+ * the write operation completes. If wbc->sync_mode is
+ * WB_SYNC_NONE, writepage() doesn't have to try too hard if
+ * there are problems, and may choose to write out other pages
+ * from the mapping if that is easier (e.g. due to internal
+ * dependencies). If it chooses not to start writeout, it
+ * should return AOP_WRITEPAGE_ACTIVATE so that the VM will not
+ * keep calling writepage() on that page. See
+ * Documentation/filesystems/Locking for more details.
+ */
int (*writepage)(struct page *page, struct writeback_control *wbc);
+
+ /**
+ * @readpage: Called by the VM to read a page from backing
+ * store. The page will be locked when readpage is called, and
+ * should be unlocked and marked uptodate once the read
+ * completes. If readpage() discovers that it needs to unlock
+ * the page for some reason, it can do so, and then return
+ * AOP_TRUNCATED_PAGE. In this case, the page will be
+ * relocated, relocked and if that all succeeds, readpage() will
+ * be called again.
+ */
int (*readpage)(struct file *, struct page *);

- /* Write back some dirty pages from this mapping. */
+ /**
+ * @writepages: Write back some dirty pages from this mapping.
+ * Called by the VM to write out pages associated with the
+ * address_space object. If wbc->sync_mode is WBC_SYNC_ALL,
+ * then the writeback_control will specify a range of pages that
+ * must be written out. If it is WBC_SYNC_NONE, then a
+ * nr_to_write is given and that many pages should be written if
+ * possible. If no writepages() is given, then
+ * ampage_writepages() is used instead. This will choose pages
+ * from the address space that are tagged as DIRTY and will pass
+ * them to writepage().
+ */
int (*writepages)(struct address_space *, struct writeback_control *);

- /* Set a page dirty. Return true if this dirtied it */
+ /**
+ * @set_page_dirty: Called by the VM to set a page dirty. This
+ * is particularly needed if an address space attaches private
+ * data to a page, and that data needs to be updated when a page
+ * is dirtied. This is called, for example, when a memory
+ * mapped page gets modified. If defined, it should set the
+ * PageDirty flag, and the PAGECACHE_TAG_DIRTY tag in the radix
+ * tree. Return true if this dirtied it
+ */
int (*set_page_dirty)(struct page *page);

- /*
- * Reads in the requested pages. Unlike ->readpage(), this is
- * PURELY used for read-ahead!.
+ /**
+ * @readpages: Called by the VM to read pages associated with
+ * the address_space object. This is essentially just a vector
+ * version of readpage(). Instead of just one page, several
+ * pages are requested. Unlike ->readpage(), readpages() is
+ * only used for read-ahead, so read errors are ignored. If
+ * anything goes wrong, feel free to give up.
*/
int (*readpages)(struct file *filp, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages);

+ /**
+ * @write_begin: Called by the generic buffered write code to
+ * ask the filesystem to prepare to write len bytes at the given
+ * offset in the file. The address_space should check that the
+ * write will be able to complete, by allocating space if
+ * necessary and doing any other internal housekeeping. If the
+ * write will update parts of any basic-blocks on storage, then
+ * those blocks should be pre-read (if they haven't been read
+ * already) so that the updated blocks can be written out
+ * properly. The filesystem must return the locked pagecache
+ * page for the specified offset, in ``*pagep``, for the caller
+ * to write into. It must be able to cope with short writes
+ * (where the length passed to write_begin is greater than the
+ * number of bytes copied into the page). flags is a field for
+ * AOP_FLAG_xxx flags, described in include/linux/fs.h. A
+ * ``void *`` may be returned in fsdata, which then gets passed
+ * into write_end(). Returns 0 on success; < 0 on failure
+ * (which is the error code), in which case write_end() is not
+ * called.
+ */
int (*write_begin)(struct file *, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata);
+
+ /**
+ * @write_end: After a successful write_begin, and data copy,
+ * write_end must be called. len is the original len passed to
+ * write_begin, and copied is the amount that was able to be
+ * copied. The filesystem must take care of unlocking the page
+ * and releasing it refcount, and updating i_size. Returns < 0
+ * on failure, otherwise the number of bytes (<= 'copied') that
+ * were able to be copied into pagecache.
+ */
int (*write_end)(struct file *, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata);

- /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
+ /*
+ * @bmap: Called by the VFS to map a logical block offset within
+ * object to physical block number. This method is used by the
+ * FIBMAP ioctl and for working with swap-files. To be able to
+ * swap to a file, the file must have a stable mapping to a
+ * block device. The swap system does not go through the
+ * filesystem but instead uses bmap to find out where the blocks
+ * in the file are and uses those addresses directly.
+ */
+/* private: Unfortunately this kludge is needed for FIBMAP. Don't use it */
sector_t (*bmap)(struct address_space *, sector_t);
+
+/* public */
+ /**
+ * @invalidatepage: If a page has PagePrivate set, then
+ * invalidatepage will be called when part or all of the page is
+ * to be removed from the address space. This generally
+ * corresponds to either a truncation, punch hole or a complete
+ * invalidation of the address space (in the latter case
+ * 'offset' will always be 0 and 'length' will be PAGE_SIZE).
+ * Any private data associated with the page should be updated
+ * to reflect this truncation. If offset is 0 and length is
+ * PAGE_SIZE, then the private data should be released, because
+ * the page must be able to be completely discarded. This may
+ * be done by calling the ->releasepage function, but in this
+ * case the release MUST succeed.
+ */
void (*invalidatepage)(struct page *, unsigned int offset,
unsigned int length);
+
+ /**
+ * @releasepage: Releasepage is called on PagePrivate pages to
+ * indicate that the page should be freed if possible.
+ * ->releasepage should remove any private data from the page
+ * and clear the PagePrivate flag. If releasepage() fails for
+ * some reason, it must indicate failure with a 0 return value.
+ * releasepage() is used in two distinct though related cases.
+ * The first is when the VM finds a clean page with no active
+ * users and wants to make it a free page. If ->releasepage
+ * succeeds, the page will be removed from the address_space and
+ * become free. The second case is when a request has been made
+ * to invalidate some or all pages in an address_space. This
+ * can happen through the fadvise(POSIX_FADV_DONTNEED) system
+ * call or by the filesystem explicitly requesting it as nfs and
+ * 9fs do (when they believe the cache may be out of date with
+ * storage) by calling invalidate_inode_pages2(). If the
+ * filesystem makes such a call, and needs to be certain that
+ * all pages are invalidated, then its releasepage will need to
+ * ensure this. Possibly it can clear the PageUptodate bit if
+ * it cannot free private data yet.
+ */
int (*releasepage)(struct page *, gfp_t);
+
+ /**
+ * @freepage: Freepage is called once the page is no longer
+ * visible in the page cache in order to allow the cleanup of
+ * any private data. Since it may be called by the memory
+ * reclaimer, it should not assume that the original
+ * address_space mapping still exists, and it should not block.
+ */
void (*freepage)(struct page *);
+
+ /**
+ * @direct_IO: Called by the generic read/write routines to
+ * perform direct_IO - that is IO requests which bypass the page
+ * cache and transfer data directly between the storage and the
+ * application's address space.
+ */
ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
- /*
- * migrate the contents of a page to the specified target. If
- * migrate_mode is MIGRATE_ASYNC, it must not block.
+
+ /**
+ * @migratepage: This is used to compact the physical memory
+ * usage. If the VM wants to relocate a page (maybe off a
+ * memory card that is signalling imminent failure) it will pass
+ * a new page and an old page to this function. migratepage()
+ * should transfer any private data across and update any
+ * references that it has to the page. If migrate_mode is
+ * MIGRATE_ASYNC, it must not block.
*/
int (*migratepage)(struct address_space *mapping,
struct page *newpage, struct page *page,
enum migrate_mode mode);
+
+ /**
+ * @isolate_page: Called by the VM when isolating a movable
+ * non-lru page. If page is successfully isolated, VM marks the
+ * page as PG_isolated via __SetPageIsolated.
+ */
bool (*isolate_page)(struct page *, isolate_mode_t);
+
+ /**
+ * @putback_page: Called by the VM when isolated page's
+ * migration fails.
+ */
void (*putback_page)(struct page *);
+
+ /**
+ * @launder_page: Called before freeing a page - it writes back
+ * the dirty page. To prevent redirtying the page, it is kept
+ * locked during the whole operation.
+ */
int (*launder_page)(struct page *);
+
+ /**
+ * @is_partially_uptodate: Called by the VM when reading a file
+ * through the pagecache when the underlying blocksize !=
+ * pagesize. If the required block is up to date then the read
+ * can complete without needing the IO to bring the whole page
+ * up to date.
+ */
int (*is_partially_uptodate)(struct page *, unsigned long from,
unsigned long count);
+
+ /**
+ * @is_dirty_writeback: Called by the VM when attempting to
+ * reclaim a page. The VM uses dirty and writeback information
+ * to determine if it needs to stall to allow flushers a chance
+ * to complete some IO. Ordinarily it can use PageDirty and
+ * PageWriteback but some filesystems have more complex state
+ * (unstable pages in NFS prevent reclaim) or do not set those
+ * flags due to locking problems. This callback allows a
+ * filesystem to indicate to the VM if a page should be treated
+ * as dirty or writeback for the purposes of stalling.
+ */
void (*is_dirty_writeback)(struct page *, bool *dirty, bool *writeback);
+
+ /**
+ * @error_remove_page: Normally set to generic_error_remove_page
+ * if truncation is ok for this address space. Used for memory
+ * failure handling. Setting this implies you deal with pages
+ * going away under you, unless you have them locked or
+ * reference counts increased.
+ */
int (*error_remove_page)(struct address_space *, struct page *);

- /* swapfile support */
+ /**
+ * @swap_activate: Called when swapon is used on a file to
+ * allocate space if necessary and pin the block lookup
+ * information in memory. A return value of zero indicates
+ * success, in which case this file can be used to back
+ * swapspace.
+ */
int (*swap_activate)(struct swap_info_struct *sis, struct file *file,
sector_t *span);
+
+ /**
+ * @swap_deactivate: Called during swapoff on files where
+ * swap_activate was successful.
+ */
void (*swap_deactivate)(struct file *file);
};

@@ -1784,83 +1993,444 @@ struct block_device_operations;

struct iov_iter;

+/**
+ * struct file_operations - Describe how the VFS can manipulate an open
+ * file.
+ * @owner: Module owner.
+ * @mmap_supported_flags: TODO: document this
+ *
+ * Note that the file operations are implemented by the specific
+ * filesystem in which the inode resides. When opening a device node
+ * (character or block special) most filesystems will call special
+ * support routines in the VFS which will locate the required device
+ * driver information. These support routines replace the filesystem
+ * file operations with those for the device driver, and then proceed to
+ * call the new open() method for the file. This is how opening a
+ * device file in the filesystem eventually ends up calling the device
+ * driver open() method.
+ *
+ * All methods are called without any locks being held, unless otherwise
+ * noted.
+ */
struct file_operations {
struct module *owner;
+
+ /**
+ * @llseek: Called when the VFS needs to move the file position
+ * index.
+ */
loff_t (*llseek)(struct file *, loff_t, int whence);
- ssize_t (*read)(struct file *, char __user *buf, size_t bufsz,
+
+ /**
+ * @read: Called by read(2) and related system calls.
+ */
+ ssize_t (*read)(struct file *filp, char __user *buf, size_t bufsz,
loff_t *ppos);
- ssize_t (*write)(struct file *, const char __user *buf, size_t bufsz,
- loff_t *ppos);
+
+ /**
+ * @write: Called by write(2) and related system calls.
+ */
+ ssize_t (*write)(struct file *filp, const char __user *buf,
+ size_t bufsz, loff_t *ppos);
+
+ /**
+ * @read_iter: Possibly asynchronous read with iov_iter as
+ * destination.
+ */
ssize_t (*read_iter)(struct kiocb *, struct iov_iter *);
+
+ /**
+ * @write_iter: Possibly asynchronous write with iov_iter as
+ * source.
+ */
ssize_t (*write_iter)(struct kiocb *, struct iov_iter *);
+
+ /**
+ * @iterate: Called when the VFS needs to read the directory
+ * contents.
+ */
int (*iterate)(struct file *, struct dir_context *);
+
+ /**
+ * @iterate_shared: Called when the VFS needs to read the
+ * directory contents when filesystem supports concurrent dir
+ * iterators.
+ */
int (*iterate_shared)(struct file *, struct dir_context *);
+
+ /**
+ * @poll: Called by the VFS when a process wants to check if
+ * there is activity on this file and (optionally) go to sleep
+ * until there is activity. Called by the select(2) and poll(2)
+ * system calls.
+ */
__poll_t (*poll)(struct file *, struct poll_table_struct *);
+
+ /**
+ * @unlocked_ioctl: Called by the ioctl(2) system call.
+ */
long (*unlocked_ioctl)(struct file *, unsigned int cmd, unsigned long arg);
+
+ /**
+ * @compat_ioctl: Called by the ioctl(2) system call when 32 bit
+ * system calls are used on 64 bit kernels.
+ */
long (*compat_ioctl)(struct file *, unsigned int cmd, unsigned long arg);
+
+ /**
+ * @mmap: Called by the mmap(2) system call.
+ */
int (*mmap)(struct file *, struct vm_area_struct *);
+
unsigned long mmap_supported_flags;
+
+ /**
+ * @open: Called by the VFS when an inode should be opened.
+ * When the VFS opens a file, it creates a new "struct file".
+ * It then calls the open method for the newly allocated file
+ * structure. You might think that the open method really
+ * belongs in ``* struct inode_operations``, and you may be
+ * right. I think it's done the way it is because it makes
+ * filesystems simpler to implement. The open() method is a
+ * good place to initialize the ``* private_data`` member in the
+ * file structure if you want to point to a device structure.
+ */
int (*open)(struct inode *, struct file *);
+
+ /**
+ * @flush: Called by the close(2) system call to flush a file.
+ */
int (*flush)(struct file *, fl_owner_t id);
+
+ /**
+ * @release: Called when the last reference to an open file is
+ * closed.
+ */
int (*release)(struct inode *, struct file *);
+
+ /**
+ * @fsync: Called by the fsync(2) system call. (Also see
+ * vfs.rst section "Handling errors during writeback".)
+ */
int (*fsync)(struct file *, loff_t start, loff_t end, int datasync);
+
+ /**
+ * @fasync: Called by the fcntl(2) system call when asynchronous
+ * (non-blocking) mode is enabled for a file.
+ */
int (*fasync)(int fd, struct file *, int flags);
+
+ /**
+ * @lock: Called by the fcntl(2) system call for F_GETLK,
+ * F_SETLK, and F_SETLKW commands.
+ */
int (*lock)(struct file *, int cmd, struct file_lock *);
+
+ /**
+ * @sendpage: TODO: document this
+ */
ssize_t (*sendpage)(struct file *, struct page *, int, size_t, loff_t *, int);
+
+ /**
+ * @get_unmapped_area: Called by the mmap(2) system call.
+ */
unsigned long (*get_unmapped_area)(struct file *, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags);
+
+ /**
+ * @check_flags: Called by the fcntl(2) system call for F_SETFL
+ * command.
+ */
int (*check_flags)(int flags);
+
+ /**
+ * @flock: Called by the flock(2) system call.
+ */
int (*flock)(struct file *, int cmd, struct file_lock *);
+
+ /**
+ * @splice_write: Called by the VFS to splice data from a pipe
+ * to a file. This method is used by the splice(2) system call
+ */
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *,
size_t len, unsigned int flags);
+
+ /**
+ * @splice_read: Called by the VFS to splice data from file to a
+ * pipe. This method is used by the splice(2) system call.
+ */
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *,
size_t len, unsigned int flags);
+
+ /**
+ * @setlease: Called by the VFS to set or release a file lock
+ * lease. setlease implementations should call generic_setlease
+ * to record or remove the lease in the inode after setting it.
+ */
int (*setlease)(struct file *, long arg, struct file_lock **, void **priv);
+
+ /**
+ * @fallocate: Called by the VFS to preallocate blocks or punch
+ * a hole.
+ */
long (*fallocate)(struct file *, int mode, loff_t offset, loff_t len);
+
+ /**
+ * @show_fdinfo: TODO: document this
+ */
void (*show_fdinfo)(struct seq_file *m, struct file *f);
+
#ifndef CONFIG_MMU
+ /**
+ * @mmap_capabilities: TODO: document this
+ */
unsigned (*mmap_capabilities)(struct file *);
#endif
+
+ /**
+ * @copy_file_range: Called by the copy_file_range(2) system
+ * call.
+ */
ssize_t (*copy_file_range)(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
size_t len, unsigned int copy_flags);
+
+ /**
+ * @remap_file_range: Called by the ioctl(2) system call for
+ * FICLONERANGE and FICLONE and FIDEDUPERANGE commands to remap
+ * file ranges. An implementation should remap len bytes at
+ * pos_in of the source file into the dest file at pos_out.
+ * Implementations must handle callers passing in len == 0; this
+ * means "remap to the end of the source file". The return
+ * value should the number of bytes remapped, or the usual
+ * negative error code if errors occurred before any bytes were
+ * remapped. The remap_flags parameter accepts ``REMAP_FILE_*``
+ * flags. If REMAP_FILE_DEDUP is set then the implementation
+ * must only remap if the requested file ranges have identical
+ * contents. If REMAP_CAN_SHORTEN is set, the caller is ok with
+ * the implementation shortening the request length to satisfy
+ * alignment or EOF requirements (or any other reason).
+ */
loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
loff_t len, unsigned int remap_flags);
+
+ /**
+ * @fadvise: Possibly called by the fadvise64() system call.
+ */
int (*fadvise)(struct file *, loff_t offset, loff_t len, int advice);
} __randomize_layout;

+/**
+ * struct inode_operations - Describes how the VFS can manipulate an
+ * inode in your filesystem.
+ *
+ * All methods are called without any locks being held, unless otherwise
+ * noted.
+ */
struct inode_operations {
+ /**
+ * @lookup: Called when the VFS needs to look up an inode in a
+ * parent directory. The name to look for is found in the
+ * dentry. This method must call d_add() to insert the found
+ * inode into the dentry. The "i_count" field in the inode
+ * structure should be incremented. If the named inode does not
+ * exist a NULL inode should be inserted into the dentry (this
+ * is called a negative dentry). Returning an error code from
+ * this routine must only be done on a real error, otherwise
+ * creating inodes with system calls like create(2), mknod(2),
+ * mkdir(2) and so on will fail. If you wish to overload the
+ * dentry methods then you should initialise the "d_dop" field
+ * in the dentry; this is a pointer to a &struct
+ * dentry_operations. This method is called with the directory
+ * inode semaphore held.
+ */
struct dentry * (*lookup)(struct inode *dir, struct dentry *dentry,
unsigned int flags);
+
+ /**
+ * @get_link: Called by the VFS to follow a symbolic link to the
+ * inode it points to. Only required if you want to support
+ * symbolic links. This method returns the symlink body to
+ * traverse (and possibly resets the current position with
+ * nd_jump_link()). If the body won't go away until the inode
+ * is gone, nothing else is needed; if it needs to be otherwise
+ * pinned, arrange for its release by having get_link(..., ...,
+ * done) do set_delayed_call(done, destructor, argument). In
+ * that case destructor(argument) will be called once VFS is
+ * done with the body you've returned. May be called in RCU
+ * mode; that is indicated by %NULL dentry argument. If request
+ * can't be handled without leaving RCU mode, have it return
+ * ERR_PTR(-ECHILD).
+ */
const char * (*get_link)(struct dentry *, struct inode *, struct delayed_call *);
+
+ /**
+ * @permission: Called by the VFS to check for access rights on
+ * a POSIX-like filesystem. May be called in rcu-walk mode
+ * (mask & MAY_NOT_BLOCK). If in rcu-walk mode, the filesystem
+ * must check the permission without blocking or storing to the
+ * inode. If a situation is encountered that rcu-walk cannot
+ * handle, return -ECHILD and it will be called again in
+ * ref-walk mode.
+ */
int (*permission)(struct inode *, int mask);
+ /**
+ * @get_acl: Called when doing permission checks on an inode.
+ */
struct posix_acl * (*get_acl)(struct inode *inode, int type);

+ /**
+ * @readlink: This is now just an override for use by
+ * readlink(2) for the cases when ->get_link uses nd_jump_link()
+ * or object is not in fact a symlink. Normally filesystems
+ * should only implement ->get_link for symlinks and readlink(2)
+ * will automatically use that.
+ */
int (*readlink)(struct dentry *, char __user *buf, int bufsz);

+ /**
+ * @create: Called by the open(2) and creat(2) system calls.
+ * Only required if you want to support regular files. The
+ * dentry you get should not have an inode (i.e. it should be a
+ * negative dentry). Here you will probably call
+ * d_instantiate() with the dentry and the newly created inode.
+ */
int (*create)(struct inode *, struct dentry *, umode_t, bool);
+
+ /**
+ * @link: Called by the link(2) system call. Only required if
+ * you want to support hard links. You will probably need to
+ * call d_instantiate() just as you would in the create()
+ * method.
+ */
int (*link)(struct dentry *, struct inode *, struct dentry *);
+
+ /**
+ * @unlink: Called by the unlink(2) system call. Only required
+ * if you want to support deleting inodes.
+ */
int (*unlink)(struct inode *, struct dentry *);
+
+ /**
+ * @symlink: Called by the symlink(2) system call. Only
+ * required if you want to support symlinks. You will probably
+ * need to call d_instantiate() just as you would in the
+ * create() method.
+ */
int (*symlink)(struct inode *, struct dentry *, const char *symname);
+
+ /**
+ * @mkdir: Called by the mkdir(2) system call. Only required if
+ * you want to support creating subdirectories. You will
+ * probably need to call d_instantiate() just as you would in
+ * the create() method.
+ */
int (*mkdir)(struct inode *, struct dentry *, umode_t);
+
+ /**
+ * @rmdir: Called by the rmdir(2) system call. Only required if
+ * you want to support deleting subdirectories.
+ */
int (*rmdir)(struct inode *, struct dentry *);
+
+ /**
+ * @mknod: Called by the mknod(2) system call to create a device
+ * (char, block) inode or a named pipe (FIFO) or socket. Only
+ * required if you want to support creating these types of
+ * inodes. You will probably need to call d_instantiate() just
+ * as you would in the create() method.
+ */
int (*mknod)(struct inode *, struct dentry *, umode_t, dev_t);
+
+ /**
+ * @rename: Called by the rename(2) system call to rename the object to
+ * have the parent and name given by the second inode and
+ * dentry. The filesystem must return -EINVAL for any
+ * unsupported or unknown flags. Currently the following flags
+ * are implemented:
+ *
+ * 1. RENAME_NOREPLACE: this flag indicates that if the target
+ * of the rename exists the rename should fail with -EEXIST
+ * instead of replacing the target. The VFS already checks
+ * for existence, so for local filesystems the
+ * RENAME_NOREPLACE implementation is equivalent to plain
+ * rename.
+ *
+ * 2. RENAME_EXCHANGE: exchange source and target. Both must
+ * exist; this is checked by the VFS. Unlike plain rename,
+ * source and target may be of different type.
+ */
int (*rename)(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_dentry,
unsigned int flags);
+
+ /**
+ * @setattr: Called by the VFS to set attributes for a file.
+ * This method is called by chmod(2) and related system calls.
+ */
int (*setattr)(struct dentry *, struct iattr *);
+
+ /**
+ * @getattr: Called by the VFS to get attributes of a file.
+ * This method is called by stat(2) and related system calls.
+ */
int (*getattr)(const struct path *, struct kstat *,
u32 request_mask, unsigned int flags);
+
+ /**
+ * @listxattr: Called by the VFS to list all extended attributes
+ * for a given file. This method is called by the listxattr(2)
+ * system call.
+ */
ssize_t (*listxattr)(struct dentry *, char *buf, size_t bufsz);
+
+ /**
+ * @fiemap: Called by the VFS in order to support fiemap (see
+ * Documentation/filesystems/fiemap.txt).
+ */
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
u64 len);
+
+ /**
+ * @update_time: Called by the VFS to update a specific time or
+ * the i_version of an inode. If this is not defined the VFS
+ * will update the inode itself and call
+ * mark_inode_dirty_sync().
+ */
int (*update_time)(struct inode *, struct timespec64 *, int flags);
+
+ /**
+ * @atomic_open: Called on the last component of an open. Using
+ * this optional method the filesystem can look up, possibly
+ * create and open the file in one atomic operation. If it
+ * wants to leave actual opening to the caller (e.g. if the file
+ * turned out to be a symlink, device, or just something
+ * filesystem won't do atomic open for), it may signal this by
+ * returning finish_no_open(file, dentry). This method is only
+ * called if the last component is negative or needs lookup.
+ * Cached positive dentries are still handled by f_op->open().
+ * If the file was created, FMODE_CREATED flag should be set in
+ * file->f_mode. In case of O_EXCL the method must only succeed
+ * if the file didn't exist and hence FMODE_CREATED shall always
+ * be set on success.
+ */
int (*atomic_open)(struct inode *, struct dentry *,
struct file *, unsigned open_flag,
umode_t create_mode);
+
+ /**
+ * @tmpfile: Called in the end of O_TMPFILE open(). Optional,
+ * equivalent to atomically creating, opening and unlinking a
+ * file in given directory.
+ */
int (*tmpfile)(struct inode *, struct dentry *, umode_t);
+
+ /**
+ * @set_acl: Called by the VFS to set the access or default ACL
+ * of an inode.
+ */
int (*set_acl)(struct inode *, struct posix_acl *, int type);
} ____cacheline_aligned;

@@ -1909,39 +2479,203 @@ extern loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos,
struct file *dst_file, loff_t dst_pos,
loff_t len, unsigned int remap_flags);

-
+/**
+ * struct super_operations - Describes how the VFS can manipulate the
+ * filesystem superblock.
+ *
+ * All methods are called without any locks being held, unless otherwise
+ * noted. This means that most methods can block safely. All methods
+ * are only called from a process context (i.e. not from an interrupt
+ * handler or bottom half).
+ *
+ * Whoever sets up the inode is responsible for filling in the "i_op"
+ * field. This is a pointer to a &struct inode_operations which
+ * describes the methods that can be performed on individual inodes.
+ *
+ * All methods are called without any locks being held, unless otherwise
+ * noted. This means that most methods can block safely. All methods
+ * are only called from a process context (i.e. not from an interrupt
+ * handler or bottom half).
+ */
struct super_operations {
+ /**
+ * @alloc_inode: This method is called by alloc_inode() to
+ * allocate memory for struct inode and initialize it. If this
+ * function is not defined, a simple 'struct inode' is
+ * allocated. Normally alloc_inode() will be used to allocate a
+ * larger structure which contains a &struct inode embedded
+ * within it.
+ */
struct inode *(*alloc_inode)(struct super_block *sb);
+
+ /**
+ * @destroy_inode: This method is called by destroy_inode() to release
+ * resources allocated for struct inode. It is only required if
+ * ->alloc_inode was defined and simply undoes anything done by
+ * ->alloc_inode.
+ */
void (*destroy_inode)(struct inode *);

+ /**
+ * @dirty_inode: This method is called by the VFS to mark an
+ * inode dirty.
+ */
void (*dirty_inode)(struct inode *, int flags);
+
+ /**
+ * @write_inode: This method is called when the VFS needs to write an
+ * inode to disc. The second parameter indicates whether the write
+ * should be synchronous or not, not all filesystems check this flag.
+ */
int (*write_inode)(struct inode *, struct writeback_control *wbc);
+
+ /**
+ * @drop_inode: Called when the last access to the inode is
+ * dropped, with the inode->i_lock spinlock held. This method
+ * should be either %NULL (normal UNIX filesystem semantics) or
+ * generic_delete_inode()(for filesystems that do not want to
+ * cache inodes - causing delete_inode() to always be called
+ * regardless of the value of ->i_nlink). The
+ * generic_delete_inode() behavior is equivalent to the old
+ * practice of using force_delete() in the put_inode() case, but
+ * does not have the races that the force_delete() approach had.
+ */
int (*drop_inode)(struct inode *);
+
+ /**
+ * @evict_inode: Hybrid of ->clear_inode() and ->delete_inode()
+ * If present, does all fs work to be done when in-core inode
+ * is about to be gone, for whatever reason.
+ */
void (*evict_inode)(struct inode *);
+
+ /**
+ * @put_super: Called when the VFS wishes to free the
+ * superblock i.e. unmount). This is called with the
+ * superblock lock held.
+ */
void (*put_super)(struct super_block *);
+
+ /**
+ * @sync_fs: Called when VFS is writing out all dirty data
+ * associated with a superblock. The second parameter
+ * indicates whether the method should wait until the write out
+ * has been completed. Optional.
+ */
int (*sync_fs)(struct super_block *sb, int wait);
+
+ /**
+ * @freeze_super: Called when the VFS is syncing the sb to make
+ * sure the filesystem is consistent and calls the fs's
+ * freeze_fs().
+ */
int (*freeze_super)(struct super_block *);
+
+ /**
+ * @freeze_fs: Called when VFS is locking a filesystem and
+ * forcing it into a consistent state. This method is
+ * currently used by the Logical Volume Manager (LVM).
+ */
int (*freeze_fs)(struct super_block *);
+
+ /**
+ * @thaw_super: Called when the VFS is unlocking the filesystem
+ * and marks it writeable again after freeze_super().
+ */
int (*thaw_super)(struct super_block *);
+
+ /**
+ * @unfreeze_fs: Called when VFS is unlocking a filesystem and
+ * making it writable again.
+ */
int (*unfreeze_fs)(struct super_block *);
+
+ /**
+ * @statfs: Called when the VFS needs to get filesystem statistics.
+ */
int (*statfs)(struct dentry *, struct kstatfs *);
+
+ /**
+ * @remount_fs: Called when the filesystem is remounted. This
+ * is called with the kernel lock held.
+ */
int (*remount_fs)(struct super_block *, int *flags, char *options);
+
+ /**
+ * @umount_begin: Called when the VFS is unmounting a filesystem.
+ */
void (*umount_begin)(struct super_block *);

+ /**
+ * @show_options: Called by the VFS to show mount options for
+ * /proc/<pid>/mounts (see vfs.rst "Mount Options" section).
+ */
int (*show_options)(struct seq_file *, struct dentry *);
+
+ /**
+ * @show_devname: Called by @show_options and @show_stats to
+ * show the device name.
+ */
int (*show_devname)(struct seq_file *, struct dentry *);
+
+ /**
+ * @show_path: Called by @show_options to show the path. (FIXME which path?)
+ */
int (*show_path)(struct seq_file *, struct dentry *);
+
+ /**
+ * @show_stats: Called by the VFS to show mount stats in
+ * /proc/<pid>mountstats.
+ */
int (*show_stats)(struct seq_file *, struct dentry *);
+
#ifdef CONFIG_QUOTA
+ /**
+ * @quota_read: Called by the VFS to read from filesystem quota file.
+ */
ssize_t (*quota_read)(struct super_block *sb, int type, char *data,
size_t len, loff_t off);
+
+ /**
+ * @quota_write: Called by the VFS to write to filesystem quota file.
+ */
ssize_t (*quota_write)(struct super_block *sb, int type,
const char *data, size_t len, loff_t off);
+
+ /**
+ * @get_dquots: TODO: document this
+ */
struct dquot **(*get_dquots)(struct inode *);
#endif
+ /**
+ * @bdev_try_to_free_page: TODO: document this
+ */
int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
+
+ /**
+ * @nr_cached_objects: Called by the sb cache shrinking
+ * function for the filesystem to return the number of freeable
+ * cached objects it contains. Optional.
+ */
long (*nr_cached_objects)(struct super_block *,
struct shrink_control *);
+
+ /**
+ * @free_cached_objects: Called by the sb cache shrinking
+ * function for the filesystem to scan the number of objects
+ * indicated to try to free them. Optional, but any filesystem
+ * implementing this method needs to also implement
+ * ->nr_cached_objects for it to be called correctly. We can't
+ * do anything with any errors that the filesystem might have
+ * encountered, hence the void return type. This will never be
+ * called if the VM is trying to reclaim under GFP_NOFS
+ * conditions, hence this method does not need to handle that
+ * situation itself. Implementations must include conditional
+ * reschedule calls inside any scanning loop that is done.
+ * This allows the VFS to determine appropriate scan batch
+ * sizes without having to worry about whether implementations
+ * will cause holdoff problems due to large scan batch sizes.
+ */
long (*free_cached_objects)(struct super_block *,
struct shrink_control *);
};
@@ -2180,6 +2914,24 @@ static inline void file_accessed(struct file *file)
int sync_inode(struct inode *inode, struct writeback_control *wbc);
int sync_inode_metadata(struct inode *inode, int wait);

+/**
+ * struct file_system_type - Describes a filesystem.
+ * @name: Name of the filesystem type, such as "ext2", "iso9660",
+ * "msdos" and so on.
+ * @fs_flags: Various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.).
+ * @parameters: TODO: document this.
+ * @owner: For internal VFS use; you should initialize this to
+ * THIS_MODULE in most cases.
+ * @next: For internal VFS use; you should initialize this to %NULL.
+ * @fs_supers: TODO: document this.
+ * @s_lock_key: lockdep-specific
+ * @s_umount_key: lockdep-specific
+ * @s_vfs_rename_key: TODO: document this.
+ * @s_writers_key: TODO: document this.
+ * @i_lock_key: TODO: document this.
+ * @i_mutex_key: TODO: document this.
+ * @i_mutex_dir_key: TODO: document this.
+ */
struct file_system_type {
const char *name;
int fs_flags;
@@ -2188,11 +2940,33 @@ struct file_system_type {
#define FS_HAS_SUBTYPE 4
#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
+ /**
+ * @init_fs_context: TODO: document this.
+ */
int (*init_fs_context)(struct fs_context *);
+
const struct fs_parameter_description *parameters;
+ /**
+ * @mount: The method to call when a new instance of this
+ * filesystem should be mounted. Please see vfs.rst
+ * section file_system_type for further documentation.
+ *
+ * @fs_type: Describes the filesystem, partly initialized by
+ * the specific filesystem code.
+ * @flags: The mount flags.
+ * @dev_name: The device name we are mounting.
+ * @data: Arbitrary mount options, usually comes as an ASCII string
+ * (see "Mount Options" section of Documentation/filesystems/vfs.rst).
+ */
struct dentry *(*mount)(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data);
+
+ /**
+ * @kill_sb: The method to call when an instance of this filesystem
+ * should be shut down.
+ */
void (*kill_sb)(struct super_block *);
+
struct module *owner;
struct file_system_type *next;
struct hlist_head fs_supers;
--
2.21.0


2019-03-27 05:21:27

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 24/24] docs: Convert vfs.txt to reStructuredText format

We have tidied up vfs.txt already. Also we copied the documentation for
structs and their members (specifically all the 'ops' data structures
and their methods) from vfs.txt into the appropriate source files. Now
we can convert vfs.txt to reStructuredText format.

- Include docs from source files now where possible, this makes vfs.rst
considerably shorter than vfs.txt

- Add labels so we can do RST references.

- Remove spurious 'the's
- s/the the/the/g
- One grammatically incorrect use of 'the'

- Use correct RST list format.

No other changes made to the original text by this patch.

Signed-off-by: Tobin C. Harding <[email protected]>
---
Documentation/filesystems/index.rst | 6 +
Documentation/filesystems/porting | 10 +-
Documentation/filesystems/vfs.rst | 426 ++++++++++++++++++++++++++++
include/linux/dcache.h | 8 +-
include/linux/fs.h | 14 +-
5 files changed, 446 insertions(+), 18 deletions(-)
create mode 100644 Documentation/filesystems/vfs.rst

diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst
index 605befab300b..031138043027 100644
--- a/Documentation/filesystems/index.rst
+++ b/Documentation/filesystems/index.rst
@@ -5,6 +5,12 @@ Linux Filesystems API
The Linux VFS
=============

+.. toctree::
+ :maxdepth: 2
+
+ vfs
+
+
The Filesystem types
--------------------

diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index cf43bc4dbf31..87953eef1a18 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -330,14 +330,14 @@ unreferenced dentries, and is now only called when the dentry refcount goes to
[mandatory]

.d_compare() calling convention and locking rules are significantly
-changed. Read updated documentation in Documentation/filesystems/vfs.txt (and
+changed. Read updated documentation in Documentation/filesystems/vfs.rst (and
look at examples of other filesystems) for guidance.

---
[mandatory]

.d_hash() calling convention and locking rules are significantly
-changed. Read updated documentation in Documentation/filesystems/vfs.txt (and
+changed. Read updated documentation in Documentation/filesystems/vfs.rst (and
look at examples of other filesystems) for guidance.

---
@@ -377,12 +377,12 @@ where possible.
the filesystem provides it), which requires dropping out of rcu-walk mode. This
may now be called in rcu-walk mode (nd->flags & LOOKUP_RCU). -ECHILD should be
returned if the filesystem cannot handle rcu-walk. See
-Documentation/filesystems/vfs.txt for more details.
+Documentation/filesystems/vfs.rst for more details.

permission is an inode permission check that is called on many or all
directory inodes on the way down a path walk (to check for exec permission). It
must now be rcu-walk aware (mask & MAY_NOT_BLOCK). See
-Documentation/filesystems/vfs.txt for more details.
+Documentation/filesystems/vfs.rst for more details.

--
[mandatory]
@@ -625,7 +625,7 @@ in your dentry operations instead.
--
[mandatory]
->clone_file_range() and ->dedupe_file_range have been replaced with
- ->remap_file_range(). See Documentation/filesystems/vfs.txt for more
+ ->remap_file_range(). See Documentation/filesystems/vfs.rst for more
information.
--
[recommended]
diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
new file mode 100644
index 000000000000..49a2e1a5e93d
--- /dev/null
+++ b/Documentation/filesystems/vfs.rst
@@ -0,0 +1,426 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=========================================
+Overview of the Linux Virtual File System
+=========================================
+
+Original author: Richard Gooch <[email protected]>
+
+Last updated on June 24, 2007.
+
+- Copyright (C) 1999 Richard Gooch
+- Copyright (C) 2005 Pekka Enberg
+
+
+Introduction
+============
+
+The Virtual File System (also known as the Virtual Filesystem Switch) is
+the software layer in the kernel that provides the filesystem interface
+to userspace programs. It also provides an abstraction within the
+kernel which allows different filesystem implementations to coexist.
+
+VFS system calls open(2), stat(2), read(2), write(2), chmod(2) and so on
+are called from a process context. Filesystem locking is described in
+the document Documentation/filesystems/Locking.
+
+
+Directory Entry Cache (dcache)
+------------------------------
+
+The VFS implements the open(2), stat(2), chmod(2), and similar system
+calls. The pathname argument that is passed to them is used by the VFS
+to search through the directory entry cache (also known as the dentry
+cache or dcache). This provides a very fast look-up mechanism to
+translate a pathname (filename) into a specific dentry. Dentries live
+in RAM and are never saved to disc: they exist only for performance.
+
+The dentry cache is meant to be a view into your entire filespace. As
+most computers cannot fit all dentries in the RAM at the same time, some
+bits of the cache are missing. In order to resolve your pathname into a
+dentry, the VFS may have to resort to creating dentries along the way,
+and then loading the inode. This is done by looking up the inode.
+
+
+The Inode Object
+----------------
+
+An individual dentry usually has a pointer to an inode. Inodes are
+filesystem objects such as regular files, directories, FIFOs and other
+beasts. They live either on the disc (for block device filesystems) or in
+the memory (for pseudo filesystems). Inodes that live on the disc are
+copied into memory when required and changes to the inode are written back
+to disc. A single inode can be pointed to by multiple dentries (hard
+links, for example, do this).
+
+To look up an inode requires that the VFS calls the lookup() method of
+the parent directory inode. This method is installed by the specific
+filesystem implementation that the inode lives in. Once the VFS has the
+required dentry (and hence the inode), we can do all those boring things
+like open(2) the file, or stat(2) it to peek at the inode data. The
+stat(2) operation is fairly simple: once the VFS has the dentry, it
+peeks at the inode data and passes some of it back to userspace.
+
+
+The File Object
+---------------
+
+Opening a file requires another operation: allocation of a file
+structure (this is the kernel-side implementation of file descriptors).
+The freshly allocated file structure is initialized with a pointer to
+the dentry and a set of file operation member functions. These are
+taken from the inode data. The open() file method is then called so the
+specific filesystem implementation can do its work. You can see that
+this is another switch performed by the VFS. The file structure is
+placed into the file descriptor table for the process.
+
+Reading, writing and closing files (and other assorted VFS operations)
+is done by using the userspace file descriptor to grab the appropriate
+file structure, and then calling the required file structure method to
+do whatever is required. For as long as the file is open, it keeps the
+dentry in use, which in turn means that the VFS inode is still in use.
+
+
+Registering and Mounting a Filesystem
+=====================================
+
+To register and unregister a filesystem, use the following API
+functions:
+
+.. code-block:: c
+
+ #include <linux/fs.h>
+
+ extern int register_filesystem(struct file_system_type *);
+ extern int unregister_filesystem(struct file_system_type *);
+
+The passed struct file_system_type describes your filesystem. When a
+request is made to mount a filesystem onto a directory in your
+namespace, the VFS will call the appropriate mount() method for the
+specific filesystem. New vfsmount referring to the tree returned by
+->mount() will be attached to the mountpoint, so that when pathname
+resolution reaches the mountpoint it will jump into the root of that
+vfsmount.
+
+You can see all filesystems that are registered to the kernel in the
+file /proc/filesystems.
+
+
+struct file_system_type
+-----------------------
+
+.. kernel-doc:: include/linux/fs.h
+ :functions: struct file_system_type
+
+.. _vfs_file_system_type:
+
+The mount() method must return the root dentry of the tree requested by
+caller. An active reference to its superblock must be grabbed and the
+superblock must be locked. On failure it should return ERR_PTR(error).
+
+The arguments match those of mount(2) and their interpretation depends
+on filesystem type. E.g. for block filesystems, dev_name is interpreted
+as block device name, that device is opened and if it contains a
+suitable filesystem image the method creates and initializes struct
+super_block accordingly, returning its root dentry to caller.
+
+->mount() may choose to return a subtree of existing filesystem - it
+doesn't have to create a new one. The main result from the caller's
+point of view is a reference to dentry at the root of (sub)tree to be
+attached; creation of new superblock is a common side effect.
+
+The most interesting member of the superblock structure that the mount()
+method fills in is the "s_op" field. This is a pointer to a "struct
+super_operations" which describes the next level of the filesystem
+implementation.
+
+Usually, a filesystem uses one of the generic mount() implementations
+and provides a fill_super() callback instead. The generic variants are:
+
+- ``mount_bdev()``: Mount a filesystem residing on a block device.
+
+- ``mount_nodev()``: Mount a filesystem that is not backed by a device.
+
+- ``mount_single()``: Mount a filesystem which shares the instance between
+ all mounts.
+
+A fill_super() callback implementation has the following arguments:
+
+- ``struct super_block *sb``: The superblock structure. The callback must
+ initialize this properly.
+
+- ``void *data``: Arbitrary mount options, usually comes as an ASCII string
+ (see "Mount Options" section).
+
+- ``int silent``: Whether or not to be silent on error.
+
+
+The Superblock Object
+=====================
+
+A superblock object represents a mounted filesystem.
+
+
+struct super_operations
+-----------------------
+
+.. kernel-doc:: include/linux/fs.h
+ :functions: struct super_operations
+
+
+struct xattr_handlers
+---------------------
+
+On filesystems that support extended attributes (xattrs), the s_xattr
+superblock field points to a NULL-terminated array of xattr handlers.
+Extended attributes are name:value pairs.
+
+- name: Indicates that the handler matches attributes with the specified
+ name (such as ``system.posix_acl_access``); the prefix field must be
+ NULL.
+
+- prefix: Indicates that the handler matches all attributes with the
+ specified name prefix (such as "user."); the name field must be NULL.
+
+- list: Determine if attributes matching this xattr handler should be
+ listed for a particular dentry. Used by some listxattr
+ implementations like generic_listxattr.
+
+- get: Called by the VFS to get the value of a particular extended
+ attribute. This method is called by the ``getxattr(2)`` system call.
+
+- set: Called by the VFS to set the value of a particular extended
+ attribute. When the new value is NULL, called to remove a particular
+ extended attribute. This method is called by the ``setxattr(2)`` and
+ removexattr(2) system calls.
+
+When none of the xattr handlers of a filesystem match the specified
+attribute name or when a filesystem doesn't support extended attributes,
+the various ``*xattr(2)`` system calls return -EOPNOTSUPP.
+
+
+The Inode Object
+================
+
+An inode object represents an object within the filesystem.
+
+
+struct inode_operations
+-----------------------
+
+.. kernel-doc:: include/linux/fs.h
+ :functions: struct inode_operations
+
+
+The Address Space Object
+========================
+
+The address space object is used to group and manage pages in the page
+cache. It can be used to keep track of the pages in a file (or anything
+else) and also track the mapping of sections of the file into process
+address spaces.
+
+There are a number of distinct yet related services that an
+address-space can provide. These include communicating memory pressure,
+page lookup by address, and keeping track of pages tagged as Dirty or
+Writeback.
+
+The first can be used independently to the others. The VM can try to
+either write dirty pages in order to clean them, or release clean pages
+in order to reuse them. To do this it can call the ->writepage method
+on dirty pages, and ->releasepage on clean pages with PagePrivate set.
+Clean pages without PagePrivate and with no external references will be
+released without notice being given to the address_space.
+
+To achieve this functionality, pages need to be placed on an LRU with
+lru_cache_add and mark_page_active needs to be called whenever the page
+is used.
+
+Pages are normally kept in a radix tree index by ->index. This tree
+maintains information about the PG_Dirty and PG_Writeback status of each
+page, so that pages with either of these flags can be found quickly.
+
+The Dirty tag is primarily used by mpage_writepages - the default
+->writepages method. It uses the tag to find dirty pages to call
+->writepage on. If mpage_writepages is not used (i.e. the address
+provides its own ->writepages) , the PAGECACHE_TAG_DIRTY tag is almost
+unused. write_inode_now and sync_inode do use it (through
+__sync_single_inode) to check if ->writepages has been successful in
+writing out the whole address_space.
+
+The Writeback tag is used by filemap*wait* and sync_page* functions, via
+filemap_fdatawait_range, to wait for all writeback to complete.
+
+An address_space handler may attach extra information to a page,
+typically using the 'private' field in the 'struct page'. If such
+information is attached, the PG_Private flag should be set. This will
+cause various VM routines to make extra calls into the address_space
+handler to deal with that data.
+
+An address space acts as an intermediate between storage and
+application. Data is read into the address space a whole page at a
+time, and provided to the application either by copying of the page, or
+by memory-mapping the page. Data is written into the address space by
+the application, and then written-back to storage typically in whole
+pages, however the address_space has finer control of write sizes.
+
+The read process essentially only requires 'readpage'. The write
+process is more complicated and uses write_begin/write_end or
+set_page_dirty to write data into the address_space, and writepage and
+writepages to writeback data to storage.
+
+Adding and removing pages to/from an address_space is protected by the
+inode's i_mutex.
+
+When data is written to a page, the PG_Dirty flag should be set. It
+typically remains set until writepage asks for it to be written. This
+should clear PG_Dirty and set PG_Writeback. It can be actually written
+at any point after PG_Dirty is clear. Once it is known to be safe,
+PG_Writeback is cleared.
+
+Writeback makes use of a writeback_control structure to direct the
+operations. This gives the writepage and writepages operations some
+information about the nature of and reason for the writeback request,
+and the constraints under which it is being done. It is also used to
+return information back to the caller about the result of a writepage or
+writepages request.
+
+
+Handling errors during writeback
+--------------------------------
+
+Most applications that do buffered I/O will periodically call a file
+synchronization call (fsync, fdatasync, msync or sync_file_range) to
+ensure that data written has made it to the backing store. When there
+is an error during writeback, they expect that error to be reported when
+a file sync request is made. After an error has been reported on one
+request, subsequent requests on the same file descriptor should return
+0, unless further writeback errors have occurred since the previous file
+syncronization.
+
+Ideally, the kernel would report errors only on file descriptions on
+which writes were done that subsequently failed to be written back. The
+generic pagecache infrastructure does not track the file descriptions
+that have dirtied each individual page however, so determining which
+file descriptors should get back an error is not possible.
+
+Instead, the generic writeback error tracking infrastructure in the
+kernel settles for reporting errors to fsync on all file descriptions
+that were open at the time that the error occurred. In a situation with
+multiple writers, all of them will get back an error on a subsequent
+fsync, even if all of the writes done through that particular file
+descriptor succeeded (or even if there were no writes on that file
+descriptor at all).
+
+Filesystems that wish to use this infrastructure should call
+mapping_set_error to record the error in the address_space when it
+occurs. Then, after writing back data from the pagecache in their
+file->fsync operation, they should call file_check_and_advance_wb_err to
+ensure that the struct file's error cursor has advanced to the correct
+point in the stream of errors emitted by the backing device(s).
+
+
+struct address_space_operations
+-------------------------------
+
+.. kernel-doc:: include/linux/fs.h
+ :functions: struct address_space_operations
+
+
+The File Object
+===============
+
+A file object represents a file opened by a process. This is also known
+as an "open file description" in POSIX parlance.
+
+
+struct file_operations
+----------------------
+
+.. kernel-doc:: include/linux/fs.h
+ :functions: struct file_operations
+
+
+Directory Entry Cache (dcache)
+==============================
+
+
+struct dentry_operations
+------------------------
+
+.. kernel-doc:: include/linux/dcache.h
+ :functions: struct dentry_operations
+
+.. _d_dname_example:
+
+Example implementation of the d_dname method:
+
+.. code-block:: c
+
+ static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen)
+ {
+ return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]",
+ dentry->d_inode->i_ino);
+ }
+
+
+.. _vfs_mount_options:
+
+Mount Options
+=============
+
+
+Parsing options
+---------------
+
+On mount and remount the filesystem is passed a string containing a
+comma separated list of mount options. The options can have either of
+these forms:
+
+ option
+ option=value
+
+The <linux/parser.h> header defines an API that helps parse these
+options. There are plenty of examples on how to use it in existing
+filesystems.
+
+
+Showing options
+---------------
+
+If a filesystem accepts mount options, it must define show_options() to
+show all the currently active options. The rules are:
+
+- Options MUST be shown which are not default or their values differ
+ from the default.
+
+- Options MAY be shown which are enabled by default or have their
+ default value.
+
+Options used only internally between a mount helper and the kernel (such
+as file descriptors), or which only have an effect during the mounting
+(such as ones controlling the creation of a journal) are exempt from the
+above rules.
+
+The underlying reason for the above rules is to make sure, that a mount
+can be accurately replicated (e.g. umounting and mounting again) based
+on the information found in /proc/mounts.
+
+
+Resources
+=========
+
+(Note some of these resources are not up-to-date with the latest kernel
+ version.)
+
+Creating Linux virtual filesystems. 2002
+ <http://lwn.net/Articles/13325/>
+
+The Linux Virtual File-system Layer by Neil Brown. 1999
+ <http://www.cse.unsw.edu.au/~neilb/oss/linux-commentary/vfs.html>
+
+A tour of the Linux VFS by Michael K. Johnson. 1996
+ <http://www.tldp.org/LDP/khg/HyperNews/get/fs/vfstour.html>
+
+A small trail through the Linux kernel by Andries Brouwer. 2001
+ <http://www.win.tue.nl/~aeb/linux/vfs/trail.html>
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 442bba9dcec8..f495add657c5 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -264,7 +264,8 @@ struct dentry_operations {
* quite tricky. The correct way to return for example "Hello"
* is to put it 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. (See vfs.rst for an example.)
+ * provided to take care of this.
+ * (See :ref:`vfs.rst <d_dname_example>` for an example.)
*/
char *(*d_dname)(struct dentry *, char *, int);

@@ -327,9 +328,6 @@ struct dentry_operations {
/*
* Locking rules for dentry_operations callbacks are to be found in
* Documentation/filesystems/Locking. Keep it updated!
- *
- * Further descriptions are found in Documentation/filesystems/vfs.txt.
- * Keep it updated too!
*/

/* d_flags entries */
@@ -749,8 +747,6 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper)
*
* If dentry is on a union/overlay, then return the underlying, real dentry.
* Otherwise return the dentry itself.
- *
- * See also: Documentation/filesystems/vfs.txt
*/
static inline struct dentry *d_real(struct dentry *dentry,
const struct inode *inode)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f2baf7c7e537..81fa355e0b17 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1974,7 +1974,6 @@ struct block_device_operations;
/*
* These flags control the behavior of the remap_file_range function pointer.
* If it is called with len == 0 that means "remap to end of source file".
- * See Documentation/filesystems/vfs.txt for more details about this call.
*
* REMAP_FILE_DEDUP: only remap if contents identical (i.e. deduplicate)
* REMAP_FILE_CAN_SHORTEN: caller can handle a shortened request
@@ -2607,9 +2606,10 @@ struct super_operations {
void (*umount_begin)(struct super_block *);

/**
- * @show_options: Called by the VFS to show mount options for
- * /proc/<pid>/mounts (see vfs.rst "Mount Options" section).
- */
+ * @show_options: Called by the VFS to show mount options for
+ * /proc/<pid>/mounts
+ * (see vfs.rst :ref:`Mount Options <vfs_mount_options>`).
+ */
int (*show_options)(struct seq_file *, struct dentry *);

/**
@@ -2948,15 +2948,15 @@ struct file_system_type {
const struct fs_parameter_description *parameters;
/**
* @mount: The method to call when a new instance of this
- * filesystem should be mounted. Please see vfs.rst
- * section file_system_type for further documentation.
+ * filesystem should be mounted. Please see :ref:`vfs.rst
+ * <vfs_file_system_type>` for further documentation.
*
* @fs_type: Describes the filesystem, partly initialized by
* the specific filesystem code.
* @flags: The mount flags.
* @dev_name: The device name we are mounting.
* @data: Arbitrary mount options, usually comes as an ASCII string
- * (see "Mount Options" section of Documentation/filesystems/vfs.rst).
+ * (see vfs.rst :ref:`Mount Options <vfs_mount_options>`).
*/
struct dentry *(*mount)(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data);
--
2.21.0


2019-03-27 05:21:29

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 23/24] dcache: Copy documentation to struct declaration

Currently the documentation for the struct dentry is located
in Documentation/filesystems/vfs.txt. Having documentation far away
from the code increases the chance of docs getting stale. This is
exactly what has happened, currently docs reference the 2.6.22 kernel.

The kernel has a mechanism for documenting structures in the
source/header files, we should use it. This makes reading arguable
easier because documentation is right there with the source and also
helps prevent the docs from getting stale.

Copy documentation for struct dentry from vfs.txt and locate it with
the struct declaration. Use kernel docs in preparation for including
the struct docs into the soon to be created vfs.rst

To ease review this patch does not touch vfs.txt, this file will be
converted to RST format shortly.

Cc: Jani Nikula <[email protected]>
Cc: Jonathan Corbet <[email protected]>
Signed-off-by: Tobin C. Harding <[email protected]>
---
include/linux/dcache.h | 177 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 177 insertions(+)

diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 0643c5127e1a..442bba9dcec8 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -130,20 +130,197 @@ enum dentry_d_lock_class
DENTRY_D_LOCK_NESTED
};

+/**
+ * struct dentry_operations - Describe how a filesystem can overload the
+ * standard dentry operations.
+ *
+ * Dentries and the dcache are the domain of the VFS and the individual
+ * filesystem implementations. Device drivers have no business here.
+ * These methods may be set to %NULL, as they are either optional or the
+ * VFS uses a default.
+ *
+ * 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
+ * directory.
+ */
struct dentry_operations {
+ /**
+ * @d_revalidate: Called when the VFS needs to revalidate a
+ * dentry. This is called whenever a name look-up finds a
+ * dentry in the dcache. Most local filesystems leave this as
+ * %NULL, because all their dentries in the dcache are valid.
+ * Network filesystems are different since things can change on
+ * the server without the client necessarily being aware of it.
+ *
+ * This function should return a positive value if the dentry is
+ * still valid, and zero or a negative error code if it isn't.
+ *
+ * d_revalidate may be called in rcu-walk mode (flags &
+ * LOOKUP_RCU). If in rcu-walk mode, the filesystem must
+ * revalidate the dentry without blocking or storing to the
+ * dentry, d_parent and d_inode should not be used without care
+ * (because they can change and, in d_inode case, even become
+ * %NULL under us).
+ *
+ * If a situation is encountered that rcu-walk
+ * cannot handle, return -ECHILD and it will be called again
+ * in ref-walk mode.
+ */
int (*d_revalidate)(struct dentry *, unsigned int);
+
+ /**
+ * @d_weak_revalidate: Called when the VFS needs to revalidate a
+ * "jumped" dentry. This is called when a path-walk ends at
+ * dentry that was not acquired by doing a lookup in the parent
+ * directory. This includes "/", "." and "..", as well as
+ * procfs-style symlinks and mountpoint traversal.
+ *
+ * In this case, we are less concerned with whether the dentry
+ * is still fully correct, but rather that the inode is still
+ * valid. As with d_revalidate, most local filesystems will set
+ * this to %NULL since their dcache entries are always valid.
+ *
+ * This function has the same return code semantics as
+ * d_revalidate.
+ *
+ * d_weak_revalidate is only called after leaving rcu-walk mode.
+ */
int (*d_weak_revalidate)(struct dentry *, unsigned int);
+
+ /**
+ * @d_hash: Called when the VFS adds a dentry to the hash table.
+ * The first dentry passed to d_hash is the parent directory
+ * that the name is to be hashed into.
+ *
+ * Same locking and synchronisation rules as d_compare regarding
+ * what is safe to dereference etc.
+ */
int (*d_hash)(const struct dentry *, struct qstr *);
+
+ /**
+ * @d_compare: Called to compare a dentry name with a given name. The first
+ * dentry is the parent of the dentry to be compared, the second is
+ * the child dentry. len and name string are properties of the dentry
+ * to be compared. qstr is the name to compare it with.
+ *
+ * Must be constant and idempotent, and should not take locks if
+ * possible, and should not or store into the dentry.
+ * Should not dereference pointers outside the dentry without
+ * lots of care (eg. d_parent, d_inode, d_name should not be used).
+ *
+ * However, our vfsmount is pinned, and RCU held, so the dentries and
+ * inodes won't disappear, neither will our sb or filesystem module.
+ * ->d_sb may be used.
+ *
+ * It is a tricky calling convention because it needs to be called under
+ * "rcu-walk", ie. without any locks or references on things.
+ */
int (*d_compare)(const struct dentry *,
unsigned int, const char *, const struct qstr *);
+
+ /**
+ * @d_delete: Called when the last reference to a dentry is
+ * dropped and the dcache is deciding whether or not to cache
+ * it. Return 1 to delete immediately, or 0 to cache the
+ * dentry. Default is %NULL which means to always cache a
+ * reachable dentry. d_delete() must be constant and idempotent.
+ */
int (*d_delete)(const struct dentry *);
+
+ /**
+ * @d_init: Called when a dentry is allocated.
+ */
int (*d_init)(struct dentry *);
+
+ /**
+ * @d_release: Called when a dentry is really deallocated.
+ */
void (*d_release)(struct dentry *);
+
+ /**
+ * @d_prune: Called by the VFS to inform the fs that this dentry
+ * is about to be unhashed and destroyed.
+ */
void (*d_prune)(struct dentry *);
+
+ /**
+ * @d_iput: Called when a dentry loses its inode (just prior to
+ * its being deallocated). The default when this is %NULL is
+ * that the VFS calls iput(). If you define this method, you
+ * must call iput() yourself.
+ */
void (*d_iput)(struct dentry *, struct inode *);
+
+ /**
+ * @d_dname: Called when the pathname of a dentry should be
+ * generated. Useful for some pseudo filesystems (sockfs,
+ * pipefs, ...) to delay pathname generation. (Instead of doing
+ * it when dentry is created, it's done only when the path is
+ * needed.). Real filesystems probably dont want to use it,
+ * because their dentries are present in global dcache hash, so
+ * their hash should be an invariant. As no lock is held,
+ * d_dname() should not try to modify the dentry itself, unless
+ * appropriate SMP safety is used. CAUTION : d_path() logic is
+ * quite tricky. The correct way to return for example "Hello"
+ * is to put it 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. (See vfs.rst for an example.)
+ */
char *(*d_dname)(struct dentry *, char *, int);
+
+ /**
+ * @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 caller. The caller is
+ * supplied with a path parameter giving the automount directory
+ * to describe the automount target and the parent VFS mount
+ * record to provide inheritable mount parameters. %NULL should
+ * be returned if someone else managed to make the automount
+ * first. If the vfsmount creation failed, then an error code
+ * should be returned. If -EISDIR is returned, then the
+ * directory will be treated as an ordinary directory and
+ * returned to pathwalk to continue walking. If a vfsmount is
+ * returned, the caller will attempt to mount it on the
+ * mountpoint and will remove the vfsmount from its expiration
+ * list in the case of failure. The vfsmount should be returned
+ * with 2 refs on it to prevent automatic expiration - the
+ * caller will clean up the additional ref. This function is
+ * only used if DCACHE_NEED_AUTOMOUNT is set on the dentry.
+ * This is set by __d_instantiate() if S_AUTOMOUNT is set on the
+ * inode being added.
+ */
struct vfsmount *(*d_automount)(struct path *);
+
+ /**
+ * @d_manage: Called to allow the filesystem to manage the
+ * transition from a dentry (optional). This allows autofs, for
+ * example, to hold up clients waiting to explore behind a
+ * 'mountpoint' while letting the daemon go past and construct
+ * the subtree there. 0 should be returned to let the calling
+ * process continue. -EISDIR can be returned to tell pathwalk
+ * to use this directory as an ordinary directory and to ignore
+ * anything mounted on it and not to check the automount flag.
+ * Any other error code will abort pathwalk completely. If the
+ * 'rcu_walk' parameter is true, then the caller is doing a
+ * pathwalk in RCU-walk mode. Sleeping is not permitted in this
+ * mode, and the caller can be asked to leave it and call again
+ * by returning -* ECHILD. -EISDIR may also be returned to tell
+ * pathwalk to ignore d_automount or any mounts. This function
+ * is only used if DCACHE_MANAGE_TRANSIT is set on the dentry
+ * being transited from.
+ */
int (*d_manage)(const struct path *, bool);
+
+ /**
+ * @d_real: overlay/union type filesystems implement this method
+ * to return one of the underlying dentries hidden by the
+ * overlay. It is used in two different modes: 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. With %NULL inode
+ * the topmost real underlying dentry is returned.
+ */
struct dentry *(*d_real)(struct dentry *, const struct inode *);
} ____cacheline_aligned;

--
2.21.0


2019-03-27 05:21:39

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 19/24] docs: filesystems: vfs: Use correct initial heading

Kernel RST has a preferred heading adornment scheme. Currently all the
heading adornments follow this scheme except the document heading.

Use correct heading adornment for initial heading.

Tested-by: Randy Dunlap <[email protected]>
Signed-off-by: Tobin C. Harding <[email protected]>
---
Documentation/filesystems/vfs.txt | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index b452b3fc5edc..0bc45c3a33db 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -1,5 +1,6 @@
-
- Overview of the Linux Virtual File System
+=========================================
+Overview of the Linux Virtual File System
+=========================================

Original author: Richard Gooch <[email protected]>

--
2.21.0


2019-03-27 05:21:40

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 10/24] dcache: Fix e.g. usage in comment

Use e.g. when abbreviating 'for example'.

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/dcache.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 9fc13c574bfb..141ffe27e95a 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2229,7 +2229,7 @@ EXPORT_SYMBOL(d_lookup);
* false-negative result due to unrelated rename activity.
*
* __d_lookup is slightly faster by avoiding rename_lock read seqlock,
- * however it must be used carefully, eg. with a following d_lookup in
+ * however it must be used carefully, e.g. with a following d_lookup in
* the case of failure.
*
* __d_lookup callers must be commented.
--
2.21.0


2019-03-27 05:21:42

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 11/24] dcache: Fix docstring comment for d_drop()

Currently the function docstring comment for d_drop() is combined for
d_drop() and __d_drop(). Also the comment includes information on
internal function ___d_drop(), this information does not need to be
exposed via the kernel docs.

Put internal documentation in a non-docstring comment above the relevant
function (___d_drop()).

Add docstring comments to both d_drop() and __d_drop() (both are
external functions). Make d_drop() comment very simple, pointing to
__d_drop() comment.

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/dcache.c | 41 +++++++++++++++++++++++++++--------------
1 file changed, 27 insertions(+), 14 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 141ffe27e95a..8094ae9c2d1b 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -429,21 +429,11 @@ static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry,
list_lru_isolate_move(lru, &dentry->d_lru, list);
}

-/**
- * d_drop - drop a dentry
- * @dentry: dentry to drop
- *
- * d_drop() unhashes the entry from the parent dentry hashes, so that it won't
- * be found through a VFS lookup any more. Note that this is different from
- * deleting the dentry - d_delete will try to mark the dentry negative if
- * possible, giving a successful _negative_ lookup, while d_drop will
- * just make the cache lookup fail.
- *
- * d_drop() is used mainly for stuff that wants to invalidate a dentry for some
- * reason (NFS timeouts or autofs deletes).
+/*
+ * ___d_drop() - Drop a dentry.
+ * @dentry: The dentry to drop.
*
- * __d_drop requires dentry->d_lock
- * ___d_drop doesn't mark dentry as "unhashed"
+ * Does not mark dentry as "unhashed"
* (dentry->d_hash.pprev will be LIST_POISON2, not NULL).
*/
static void ___d_drop(struct dentry *dentry)
@@ -464,6 +454,21 @@ static void ___d_drop(struct dentry *dentry)
hlist_bl_unlock(b);
}

+/**
+ * __d_drop() - Drop a dentry.
+ * @dentry: The dentry to drop.
+ *
+ * Unhashes the entry from the parent dentry hashes, so that it won't
+ * be found through a VFS lookup any more. Note that this is different
+ * from deleting the dentry - d_delete() will try to mark the dentry
+ * negative if possible, giving a successful _negative_ lookup, while
+ * __d_drop() will just make the cache lookup fail.
+ *
+ * __d_drop() is used mainly for stuff that wants to invalidate a dentry
+ * for some reason (NFS timeouts or autofs deletes).
+ *
+ * Context: Caller must hold the dentry->d_lock.
+ */
void __d_drop(struct dentry *dentry)
{
if (!d_unhashed(dentry)) {
@@ -474,6 +479,14 @@ void __d_drop(struct dentry *dentry)
}
EXPORT_SYMBOL(__d_drop);

+/**
+ * d_drop() - Drop a dentry.
+ * @dentry: The dentry to drop.
+ *
+ * Wrapper around __d_drop() that handles the locking.
+ *
+ * Context: Takes/drops the dentry->d_lock.
+ */
void d_drop(struct dentry *dentry)
{
spin_lock(&dentry->d_lock);
--
2.21.0


2019-03-27 05:21:47

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 12/24] dcache: Fix non-docstring comments

While cleaning up the docstrings for dcache lets fix any errors of
content and/or formatting in non-docstring comments also. This arguably
makes the code cleaner.

Fix non-docstring comments i.e. all the other comments excluding
function docstrings.

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/dcache.c | 39 +++++++++++++++++------------------
include/linux/dcache.h | 46 ++++++++++++++++++------------------------
2 files changed, 39 insertions(+), 46 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 8094ae9c2d1b..e513a9e9e418 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -169,7 +169,7 @@ int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer,

#include <asm/word-at-a-time.h>
/*
- * NOTE! 'cs' and 'scount' come from a dentry, so it has a
+ * NOTE! 'cs' and 'scount' come from a dentry, so it has an
* aligned allocation for this particular component. We don't
* strictly need the load_unaligned_zeropad() safety, but it
* doesn't hurt either.
@@ -500,7 +500,7 @@ static inline void dentry_unlist(struct dentry *dentry, struct dentry *parent)
struct dentry *next;
/*
* Inform d_walk() and shrink_dentry_list() that we are no longer
- * attached to the dentry tree
+ * attached to the dentry tree.
*/
dentry->d_flags |= DCACHE_DENTRY_KILLED;
if (unlikely(list_empty(&dentry->d_child)))
@@ -540,13 +540,11 @@ static void __dentry_kill(struct dentry *dentry)
if (!IS_ROOT(dentry))
parent = dentry->d_parent;

- /*
- * The dentry is now unrecoverably dead to the world.
- */
+ /* The dentry is now unrecoverably dead to the world. */
lockref_mark_dead(&dentry->d_lockref);

/*
- * inform the fs via d_prune that this dentry is about to be
+ * Inform the fs via d_prune that this dentry is about to be
* unhashed and destroyed.
*/
if (dentry->d_flags & DCACHE_OP_PRUNE)
@@ -1048,6 +1046,7 @@ static bool shrink_lock_dentry(struct dentry *dentry)
return true;
spin_unlock(&parent->d_lock);
out:
+
if (inode)
spin_unlock(&inode->i_lock);
return false;
@@ -1129,7 +1128,7 @@ static enum lru_status dentry_lru_isolate(struct list_head *item,
* This is guaranteed by the fact that all LRU management
* functions are intermediated by the LRU API calls like
* list_lru_add and list_lru_del. List movement in this file
- * only ever occur through this functions or through callbacks
+ * only ever occurs through this functions or through callbacks
* like this one, that are called from the LRU API.
*
* The only exceptions to this are functions like
@@ -1617,7 +1616,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
* We guarantee that the inline name is always NUL-terminated.
* This way the memcpy() done by the name switching in rename
* will still always have a NUL at the end, even if we might
- * be overwriting an internal NUL character
+ * be overwriting an internal NUL character.
*/
dentry->d_iname[DNAME_INLINE_LEN-1] = 0;
if (unlikely(!name)) {
@@ -1694,8 +1693,8 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
dentry->d_flags |= DCACHE_RCUACCESS;
spin_lock(&parent->d_lock);
/*
- * don't need child lock because it is not subject
- * to concurrency here
+ * Do not need child lock because it is not subject
+ * to concurrency here.
*/
__dget_dlock(parent);
dentry->d_parent = parent;
@@ -1923,7 +1922,7 @@ static struct dentry *__d_instantiate_anon(struct dentry *dentry,
goto out_iput;
}

- /* attach a disconnected dentry */
+ /* Attach a disconnected dentry. */
add_flags = d_flags_for_inode(inode);

if (disconnected)
@@ -2496,8 +2495,8 @@ struct dentry *d_alloc_parallel(struct dentry *parent,

rcu_read_unlock();
/*
- * somebody is likely to be still doing lookup for it;
- * wait for them to finish
+ * Somebody is likely to be still doing lookup for it;
+ * wait for them to finish.
*/
spin_lock(&dentry->d_lock);
d_wait_lookup(dentry);
@@ -2521,7 +2520,7 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
return dentry;
}
rcu_read_unlock();
- /* we can't take ->d_lock here; it's OK, though. */
+ /* We can't take ->d_lock here; it's OK, though. */
new->d_flags |= DCACHE_PAR_LOOKUP;
new->d_wait = wq;
hlist_bl_add_head_rcu(&new->d_u.d_in_lookup_hash, b);
@@ -2549,8 +2548,7 @@ void __d_lookup_done(struct dentry *dentry)
}
EXPORT_SYMBOL(__d_lookup_done);

-/* inode->i_lock held if inode is non-NULL */
-
+/* Caller holds inode->i_lock if inode is non-NULL */
static inline void __d_add(struct dentry *dentry, struct inode *inode)
{
struct inode *dir = NULL;
@@ -2732,7 +2730,7 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
BUG_ON(p);
spin_lock(&target->d_parent->d_lock);
} else if (!p) {
- /* target is not a descendent of dentry->d_parent */
+ /* Target is not a descendent of dentry->d_parent. */
spin_lock(&target->d_parent->d_lock);
spin_lock_nested(&old_parent->d_lock, DENTRY_D_LOCK_NESTED);
} else {
@@ -2926,7 +2924,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
if (S_ISDIR(inode->i_mode)) {
struct dentry *new = __d_find_any_alias(inode);
if (unlikely(new)) {
- /* The reference to new ensures it remains an alias */
+ /* The reference to new ensures it remains an alias. */
spin_unlock(&inode->i_lock);
write_seqlock(&rename_lock);
if (unlikely(d_ancestor(new, dentry))) {
@@ -3055,7 +3053,8 @@ __setup("dhash_entries=", set_dhash_entries);

static void __init dcache_init_early(void)
{
- /* If hashes are distributed across NUMA nodes, defer
+ /*
+ * If hashes are distributed across NUMA nodes, defer
* hash allocation until vmalloc space is available.
*/
if (hashdist)
@@ -3085,7 +3084,7 @@ static void __init dcache_init(void)
SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD|SLAB_ACCOUNT,
d_iname);

- /* Hash may have been set up in dcache_init_early */
+ /* Hash may have been set up in dcache_init_early. */
if (!hashdist)
return;

diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 2fc9fc59adb1..862aefe5a10a 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -92,8 +92,7 @@ struct dentry {
struct hlist_bl_node d_hash; /* lookup hash list */
struct dentry *d_parent; /* parent directory */
struct qstr d_name;
- struct inode *d_inode; /* Where the name belongs to - NULL is
- * negative */
+ struct inode *d_inode; /* inode for name - NULL is negative */
unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */

/* Ref lookup also touches following */
@@ -152,7 +151,7 @@ struct dentry_operations {
* Locking rules for dentry_operations callbacks are to be found in
* Documentation/filesystems/Locking. Keep it updated!
*
- * FUrther descriptions are found in Documentation/filesystems/vfs.txt.
+ * Further descriptions are found in Documentation/filesystems/vfs.txt.
* Keep it updated too!
*/

@@ -162,17 +161,18 @@ struct dentry_operations {
#define DCACHE_OP_REVALIDATE 0x00000004
#define DCACHE_OP_DELETE 0x00000008
#define DCACHE_OP_PRUNE 0x00000010
-
+/*
+ * This dentry is possibly not currently connected to the dcache tree,
+ * in which case its parent will either be itself, or will have this
+ * flag as well. nfsd will not use a dentry with this bit set, but will
+ * first endeavour to clear the bit either by discovering that it is
+ * connected, or by performing lookup operations. Any filesystem which
+ * supports nfsd_operations MUST have a lookup function which, if it
+ * finds a directory inode with a DCACHE_DISCONNECTED dentry, will
+ * d_move that dentry into place and return that dentry rather than the
+ * passed one, typically using d_splice_alias.
+ */
#define DCACHE_DISCONNECTED 0x00000020
- /* This dentry is possibly not currently connected to the dcache tree, in
- * which case its parent will either be itself, or will have this flag as
- * well. nfsd will not use a dentry with this bit set, but will first
- * endeavour to clear the bit either by discovering that it is connected,
- * or by performing lookup operations. Any filesystem which supports
- * nfsd_operations MUST have a lookup function which, if it finds a
- * directory inode with a DCACHE_DISCONNECTED dentry, will d_move that
- * dentry into place and return that dentry rather than the passed one,
- * typically using d_splice_alias. */

#define DCACHE_REFERENCED 0x00000040 /* Recently used, don't discard. */
#define DCACHE_RCUACCESS 0x00000080 /* Entry has ever been RCU-visible */
@@ -182,19 +182,17 @@ struct dentry_operations {
#define DCACHE_SHRINK_LIST 0x00000400

#define DCACHE_OP_WEAK_REVALIDATE 0x00000800
-
+/* This dentry has been "silly renamed" and has to be deleted on the last dput(). */
#define DCACHE_NFSFS_RENAMED 0x00001000
- /* this dentry has been "silly renamed" and has to be deleted on the last
- * dput() */
#define DCACHE_COOKIE 0x00002000 /* For use by dcookie subsystem */
+/* Parent inode is watched by some fsnotify listener. */
#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x00004000
- /* Parent inode is watched by some fsnotify listener */

#define DCACHE_DENTRY_KILLED 0x00008000

-#define DCACHE_MOUNTED 0x00010000 /* is a mountpoint */
-#define DCACHE_NEED_AUTOMOUNT 0x00020000 /* handle automount on this dir */
-#define DCACHE_MANAGE_TRANSIT 0x00040000 /* manage transit from this dirent */
+#define DCACHE_MOUNTED 0x00010000 /* Is a mountpoint */
+#define DCACHE_NEED_AUTOMOUNT 0x00020000 /* Handle automount on this dir */
+#define DCACHE_MANAGE_TRANSIT 0x00040000 /* Manage transit from this dirent */
#define DCACHE_MANAGED_DENTRY \
(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)

@@ -262,9 +260,7 @@ extern void d_prune_aliases(struct inode *);
/* test whether we have any submounts in a subdir tree */
extern int path_has_submounts(const struct path *);

-/*
- * This adds the entry to the hash queues.
- */
+/* This adds the entry to the hash queues. */
extern void d_rehash(struct dentry *);

extern void d_add(struct dentry *, struct inode *);
@@ -286,9 +282,7 @@ static inline unsigned d_count(const struct dentry *dentry)
return dentry->d_lockref.count;
}

-/*
- * helper function for dentry_operations.d_dname() members
- */
+/* Helper function for dentry_operations.d_dname() members. */
extern __printf(4, 5)
char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
extern char *simple_dname(struct dentry *, char *, int);
--
2.21.0


2019-03-27 05:21:50

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 13/24] dcache: Clean up function docstrings

The function docstrings for dcache are currently not in the correct
form. As part of an effort to update the documentation for the dcache
let's fix up the function docstrings to use the correct kernel
reStructuredText format.

Clean up function docstrings.

Signed-off-by: Tobin C. Harding <[email protected]>
---
fs/dcache.c | 281 +++++++++++++++++++++++------------------
include/linux/dcache.h | 43 ++++---
2 files changed, 187 insertions(+), 137 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index e513a9e9e418..7acf94290b66 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -812,8 +812,8 @@ static inline bool fast_dput(struct dentry *dentry)
* Real recursion would eat up our stack space.
*/

-/*
- * dput - release a dentry
+/**
+ * dput() - Release a dentry.
* @dentry: dentry to release
*
* Release a dentry. This will drop the usage count and if appropriate
@@ -909,11 +909,13 @@ static struct dentry * __d_find_any_alias(struct inode *inode)
}

/**
- * d_find_any_alias - find any alias for a given inode
+ * d_find_any_alias() - Find any alias for a given inode.
* @inode: inode to find an alias for
*
* If any aliases exist for the given inode, take and return a
- * reference for one of them. If no aliases exist, return %NULL.
+ * reference for one of them.
+ *
+ * Return: The found dentry reference or %NULL if no aliases exists.
*/
struct dentry *d_find_any_alias(struct inode *inode)
{
@@ -926,20 +928,6 @@ struct dentry *d_find_any_alias(struct inode *inode)
}
EXPORT_SYMBOL(d_find_any_alias);

-/**
- * d_find_alias - grab a hashed alias of inode
- * @inode: inode in question
- *
- * If inode has a hashed alias, or is a directory and has any alias,
- * acquire the reference to alias and return it. Otherwise return NULL.
- * Notice that if inode is a directory there can be only one alias and
- * it can be unhashed only if it has no children, or if it is the root
- * of a filesystem, or if the directory was renamed and d_revalidate
- * was the first vfs operation to notice.
- *
- * If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer
- * any other hashed alias over that one.
- */
static struct dentry *__d_find_alias(struct inode *inode)
{
struct dentry *alias;
@@ -959,6 +947,23 @@ static struct dentry *__d_find_alias(struct inode *inode)
return NULL;
}

+/**
+ * d_find_alias() - Grab a hashed alias of inode.
+ * @inode: inode in question
+ *
+ * If inode has a hashed alias, or is a directory and has any alias,
+ * acquire the reference to alias. Notice that if inode is a directory
+ * there can be only one alias and it can be unhashed only if it has no
+ * children, or if it is the root of a filesystem, or if the directory
+ * was renamed and d_revalidate was the first vfs operation to notice.
+ *
+ * If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer
+ * any other hashed alias over that one.
+ *
+ * Context: Takes the inode->i_lock and the dentry->d_lock for each
+ * alias i.e. for each inode->i_dentry.
+ * Return: The found dentry reference or %NULL if no alias found.
+ */
struct dentry *d_find_alias(struct inode *inode)
{
struct dentry *de = NULL;
@@ -972,9 +977,11 @@ struct dentry *d_find_alias(struct inode *inode)
}
EXPORT_SYMBOL(d_find_alias);

-/*
- * Try to kill dentries associated with this inode.
- * WARNING: you must own a reference to inode.
+/**
+ * d_prune_aliases() - Try to kill dentries associated with this inode.
+ * @inode: The inode we are working on.
+ *
+ * Context: Caller must own a reference to inode.
*/
void d_prune_aliases(struct inode *inode)
{
@@ -1148,7 +1155,7 @@ static enum lru_status dentry_lru_isolate(struct list_head *item,
}

/**
- * prune_dcache_sb - shrink the dcache
+ * prune_dcache_sb() - Shrink the dcache.
* @sb: superblock
* @sc: shrink control, passed to list_lru_shrink_walk()
*
@@ -1158,6 +1165,8 @@ static enum lru_status dentry_lru_isolate(struct list_head *item,
*
* This function may fail to free any resources if all the dentries are in
* use.
+ *
+ * Return: The number of dentries freed.
*/
long prune_dcache_sb(struct super_block *sb, struct shrink_control *sc)
{
@@ -1192,7 +1201,7 @@ static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,


/**
- * shrink_dcache_sb - shrink dcache for a superblock
+ * shrink_dcache_sb() - Shrink dcache for a superblock.
* @sb: superblock
*
* Shrink the dcache for the specified super block. This is used to free
@@ -1229,10 +1238,10 @@ enum d_walk_ret {
};

/**
- * d_walk - walk the dentry tree
- * @parent: start of walk
- * @data: data passed to @enter() and @finish()
- * @enter: callback when first entering the dentry
+ * d_walk() - Walk the dentry tree.
+ * @parent: Start of walk.
+ * @data: Data passed to @enter() and @finish().
+ * @enter: Callback when first entering the dentry.
*
* The @enter() callbacks are called with d_lock held.
*/
@@ -1362,12 +1371,11 @@ static enum d_walk_ret path_check_mount(void *data, struct dentry *dentry)
}

/**
- * path_has_submounts - check for mounts over a dentry in the
- * current namespace.
+ * path_has_submounts() - Check current namespace for mounts over a dentry.
* @parent: path to check.
*
- * Return true if the parent or its subdirectories contain
- * a mount point in the current namespace.
+ * Return: True if the parent or its subdirectories contain
+ * a mount point in the current namespace.
*/
int path_has_submounts(const struct path *parent)
{
@@ -1381,13 +1389,17 @@ int path_has_submounts(const struct path *parent)
}
EXPORT_SYMBOL(path_has_submounts);

-/*
+/**
+ * d_set_mounted() - Set a mountpoint.
+ * @dentry: The dentry we are working on.
+ *
* Called by mount code to set a mountpoint and check if the mountpoint is
* reachable (e.g. NFS can unhash a directory dentry and then the complete
* subtree can become unreachable).
*
- * Only one of d_invalidate() and d_set_mounted() must succeed. For
- * this reason take rename_lock and d_lock on dentry and ancestors.
+ * Only one of d_invalidate() and d_set_mounted() must succeed.
+ *
+ * Context: Take rename_lock and d_lock on dentry and ancestors.
*/
int d_set_mounted(struct dentry *dentry)
{
@@ -1468,7 +1480,7 @@ static enum d_walk_ret select_collect(void *_data, struct dentry *dentry)
}

/**
- * shrink_dcache_parent - prune dcache
+ * shrink_dcache_parent() - Prune dcache.
* @parent: parent of entries to prune
*
* Prune the dcache to remove unused children of the parent dentry.
@@ -1527,8 +1539,13 @@ static void do_one_tree(struct dentry *dentry)
dput(dentry);
}

-/*
- * destroy the dentries attached to a superblock on unmounting
+/**
+ * shrink_dcache_for_umount() - Destroy the dentries attached to a superblock.
+ * @sb: The superblock to shrink.
+ *
+ * Used when unmounting. Shrinks (removes unused dentries) the sb root
+ * node then verifies tree does not contain any inuse dentries. Printks
+ * a error message if any dentry is still inuse.
*/
void shrink_dcache_for_umount(struct super_block *sb)
{
@@ -1558,7 +1575,7 @@ static enum d_walk_ret find_submount(void *_data, struct dentry *dentry)
}

/**
- * d_invalidate - detach submounts, prune dcache, and drop
+ * d_invalidate() - Detach submounts, prune dcache, and drop.
* @dentry: dentry to invalidate (aka detach, prune and drop)
*/
void d_invalidate(struct dentry *dentry)
@@ -1593,15 +1610,15 @@ void d_invalidate(struct dentry *dentry)
EXPORT_SYMBOL(d_invalidate);

/**
- * __d_alloc - allocate a dcache entry
+ * __d_alloc() - Allocate a dcache entry.
* @sb: filesystem it will belong to
* @name: qstr of the name
*
- * Allocates a dentry. It returns %NULL if there is insufficient memory
- * available. On a success the dentry is returned. The name passed in is
- * copied and the copy passed in may be reused after this call.
+ * @name is copied and may be reused after this call.
+ *
+ * Return: The newly allocated dentry on success. %NULL if there is
+ * insufficient memory available or d_init() method fails.
*/
-
struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
{
struct dentry *dentry;
@@ -1677,13 +1694,16 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
}

/**
- * d_alloc - allocate a dcache entry
+ * d_alloc() - Allocate a dcache entry.
* @parent: parent of entry to allocate
* @name: qstr of the name
*
- * Allocates a dentry. It returns %NULL if there is insufficient memory
- * available. On a success the dentry is returned. The name passed in is
- * copied and the copy passed in may be reused after this call.
+ * Allocates a dentry and adds it to @parent. See __d_alloc() for full
+ * explanation of behaviour.
+ *
+ * @name is copied and may be reused after this call.
+ *
+ * Return: The newly allocated dentry or %NULL if __d_alloc() fails.
*/
struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
{
@@ -1722,7 +1742,7 @@ struct dentry *d_alloc_cursor(struct dentry * parent)
}

/**
- * d_alloc_pseudo - allocate a dentry (for lookup-less filesystems)
+ * d_alloc_pseudo() - Allocate a dentry (for lookup-less filesystems).
* @sb: the superblock
* @name: qstr of the name
*
@@ -1735,6 +1755,16 @@ struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
}
EXPORT_SYMBOL(d_alloc_pseudo);

+/**
+ * d_alloc_name() - Allocate a dcache entry.
+ * @parent: The parent of entry to allocate.
+ * @name: The name to use in the allocation.
+ *
+ * Creates a qstring from @name then allocates a dentry, adding it to
+ * @parent. See __d_alloc() for full explanation of behaviour.
+ *
+ * Return: The newly allocated dentry or %NULL if d_alloc() fails.
+ */
struct dentry *d_alloc_name(struct dentry *parent, const char *name)
{
struct qstr q;
@@ -1775,13 +1805,13 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
}
EXPORT_SYMBOL(d_set_d_op);

-
-/*
- * d_set_fallthru - Mark a dentry as falling through to a lower layer
- * @dentry - The dentry to mark
+/**
+ * d_set_fallthru() - Mark a dentry as falling through to a lower layer.
+ * @dentry: The dentry to mark.
*
- * Mark a dentry as falling through to the lower layer (as set with
- * d_pin_lower()). This flag may be recorded on the medium.
+ * Mark the dentry->d_flags to indicate that @dentry is falling through
+ * to the lower layer (as set with d_pin_lower()). This flag may be
+ * recorded on the medium.
*/
void d_set_fallthru(struct dentry *dentry)
{
@@ -1841,12 +1871,10 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
}

/**
- * d_instantiate - fill in inode information for a dentry
+ * d_instantiate() - Fill in inode information for a dentry.
* @entry: dentry to complete
* @inode: inode to attach to this dentry
*
- * Fill in inode information in the entry.
- *
* This turns negative dentries into productive full members
* of society.
*
@@ -1854,7 +1882,6 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
* (or otherwise set) by the caller to indicate that it is now
* in use by the dcache.
*/
-
void d_instantiate(struct dentry *entry, struct inode * inode)
{
BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
@@ -1867,7 +1894,11 @@ void d_instantiate(struct dentry *entry, struct inode * inode)
}
EXPORT_SYMBOL(d_instantiate);

-/*
+/**
+ * d_instantiate_new() - Instantiate dentry and unlock inode.
+ * @entry: The dentry to complete.
+ * @inode: The inode to attach to this dentry.
+ *
* This should be equivalent to d_instantiate() + unlock_new_inode(),
* with lockdep-related part of unlock_new_inode() done before
* anything else. Use that instead of open-coding d_instantiate()/
@@ -1980,7 +2011,7 @@ static struct dentry *__d_obtain_alias(struct inode *inode, bool disconnected)
}

/**
- * d_obtain_alias - find or allocate a DISCONNECTED dentry for a given inode
+ * d_obtain_alias() - Find or allocate a DISCONNECTED dentry.
* @inode: inode to allocate the dentry for
*
* Obtain a dentry for an inode resulting from NFS filehandle conversion or
@@ -2004,7 +2035,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
EXPORT_SYMBOL(d_obtain_alias);

/**
- * d_obtain_root - find or allocate a dentry for a given inode
+ * d_obtain_root() - Find or allocate a dentry for a given inode.
* @inode: inode to allocate the dentry for
*
* Obtain an IS_ROOT dentry for the root of a filesystem.
@@ -2025,7 +2056,7 @@ struct dentry *d_obtain_root(struct inode *inode)
EXPORT_SYMBOL(d_obtain_root);

/**
- * d_add_ci - lookup or allocate new dentry with case-exact name
+ * d_add_ci() - Lookup or allocate new dentry with case-exact name.
* @inode: the inode case-insensitive lookup has found
* @dentry: the negative dentry that was passed to the parent's lookup func
* @name: the case-exact name to be associated with the returned dentry
@@ -2093,11 +2124,10 @@ static inline bool d_same_name(const struct dentry *dentry,
}

/**
- * __d_lookup_rcu - search for a dentry (racy, store-free)
+ * __d_lookup_rcu() - Search for a dentry (racy, store-free).
* @parent: parent dentry
* @name: qstr of name we wish to find
* @seqp: returns d_seq value at the point where the dentry was found
- * Returns: dentry, or NULL
*
* __d_lookup_rcu is the dcache lookup function for rcu-walk name
* resolution (store-free path walking) design described in
@@ -2105,21 +2135,25 @@ static inline bool d_same_name(const struct dentry *dentry,
*
* This is not to be used outside core vfs.
*
- * __d_lookup_rcu must only be used in rcu-walk mode, ie. with vfsmount lock
- * held, and rcu_read_lock held. The returned dentry must not be stored into
- * without taking d_lock and checking d_seq sequence count against @seq
- * returned here.
+ * __d_lookup_rcu() must only be used in rcu-walk mode, i.e. with
+ * vfsmount lock held, and rcu_read_lock() held. The returned dentry
+ * must not be stored into without taking d_lock and checking d_seq
+ * sequence count against @seq returned here.
*
- * A refcount may be taken on the found dentry with the d_rcu_to_refcount
- * function.
+ * A refcount may be taken on the found dentry with the
+ * d_rcu_to_refcount() function.
+ *
+ * Alternatively, __d_lookup_rcu() may be called again to look up the
+ * child of the returned dentry, so long as its parent's seqlock is
+ * checked after the child is looked up. Thus, an interlocking stepping
+ * of sequence lock checks is formed, giving integrity down the path
+ * walk.
*
- * Alternatively, __d_lookup_rcu may be called again to look up the child of
- * the returned dentry, so long as its parent's seqlock is checked after the
- * child is looked up. Thus, an interlocking stepping of sequence lock checks
- * is formed, giving integrity down the path walk.
+ * NOTE! The caller *has* to check the resulting dentry against the
+ * sequence number we've returned before using any of the resulting
+ * dentry state!
*
- * NOTE! The caller *has* to check the resulting dentry against the sequence
- * number we've returned before using any of the resulting dentry state!
+ * Return: dentry, or %NULL.
*/
struct dentry *__d_lookup_rcu(const struct dentry *parent,
const struct qstr *name,
@@ -2206,15 +2240,16 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,
}

/**
- * d_lookup - search for a dentry
+ * d_lookup() - Search for a dentry.
* @parent: parent dentry
* @name: qstr of name we wish to find
- * Returns: dentry, or NULL
*
- * d_lookup searches the children of the parent dentry for the name in
+ * d_lookup() searches the children of the parent dentry for the name in
* question. If the dentry is found its reference count is incremented and the
* dentry is returned. The caller must use dput to free the entry when it has
- * finished using it. %NULL is returned if the dentry does not exist.
+ * finished using it.
+ *
+ * Return: dentry, or %NULL if the dentry does not exist.
*/
struct dentry *d_lookup(const struct dentry *parent, const struct qstr *name)
{
@@ -2232,19 +2267,20 @@ struct dentry *d_lookup(const struct dentry *parent, const struct qstr *name)
EXPORT_SYMBOL(d_lookup);

/**
- * __d_lookup - search for a dentry (racy)
+ * __d_lookup() - Search for a dentry (racy).
* @parent: parent dentry
* @name: qstr of name we wish to find
- * Returns: dentry, or NULL
*
- * __d_lookup is like d_lookup, however it may (rarely) return a
+ * __d_lookup() is like d_lookup(), however it may (rarely) return a
* false-negative result due to unrelated rename activity.
*
- * __d_lookup is slightly faster by avoiding rename_lock read seqlock,
- * however it must be used carefully, e.g. with a following d_lookup in
+ * __d_lookup() is slightly faster by avoiding rename_lock read seqlock,
+ * however it must be used carefully, e.g. with a following d_lookup() in
* the case of failure.
*
- * __d_lookup callers must be commented.
+ * __d_lookup() callers must be commented.
+ *
+ * Return: dentry, or %NULL.
*/
struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
{
@@ -2303,11 +2339,12 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
}

/**
- * d_hash_and_lookup - hash the qstr then search for a dentry
+ * d_hash_and_lookup() - Hash the qstr then search for a dentry.
* @dir: Directory to search in
* @name: qstr of name we wish to find
*
- * On lookup failure NULL is returned; on bad name - ERR_PTR(-error)
+ * Return: The dentry if found, %NULL on lookup failure, ERR_PTR(-error)
+ * on bad name.
*/
struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
{
@@ -2340,13 +2377,12 @@ EXPORT_SYMBOL(d_hash_and_lookup);
*/

/**
- * d_delete - delete a dentry
+ * d_delete() - Delete a dentry.
* @dentry: The dentry to delete
*
* Turn the dentry into a negative dentry if possible, otherwise
- * remove it from the hash queues so it can be deleted later
+ * remove it from the hash queues so it can be deleted later.
*/
-
void d_delete(struct dentry * dentry)
{
struct inode *inode = dentry->d_inode;
@@ -2379,7 +2415,7 @@ static void __d_rehash(struct dentry *entry)
}

/**
- * d_rehash - add an entry back to the hash
+ * d_rehash() - Add an entry back to the hash.
* @entry: dentry to add to the hash
*
* Adds a dentry to the hash according to its name.
@@ -2576,7 +2612,7 @@ static inline void __d_add(struct dentry *dentry, struct inode *inode)
}

/**
- * d_add - add dentry to hash queues
+ * d_add() - Add dentry to hash queues.
* @entry: dentry to add
* @inode: The inode to attach to this dentry
*
@@ -2595,15 +2631,13 @@ void d_add(struct dentry *entry, struct inode *inode)
EXPORT_SYMBOL(d_add);

/**
- * d_exact_alias - find and hash an exact unhashed alias
+ * d_exact_alias() - Find and hash an exact unhashed alias.
* @entry: dentry to add
* @inode: The inode to go with this dentry
*
- * If an unhashed dentry with the same name/parent and desired
- * inode already exists, hash and return it. Otherwise, return
- * NULL.
- *
- * Parent directory should be locked.
+ * Context: Parent directory should be locked.
+ * Return: If an unhashed dentry with the same name/parent and desired
+ * inode already exists, hash and return it. Otherwise %NULL.
*/
struct dentry *d_exact_alias(struct dentry *entry, struct inode *inode)
{
@@ -2702,15 +2736,17 @@ static void copy_name(struct dentry *dentry, struct dentry *target)
}

/*
- * __d_move - move a dentry
+ * __d_move() - Move a dentry.
* @dentry: entry to move
* @target: new dentry
* @exchange: exchange the two dentries
*
* Update the dcache to reflect the move of a file name. Negative
- * dcache entries should not be moved in this way. Caller must hold
- * rename_lock, the i_mutex of the source and target directories,
- * and the sb->s_vfs_rename_mutex if they differ. See lock_rename().
+ * dcache entries should not be moved in this way.
+ *
+ * Context: Caller must hold rename_lock, the i_mutex of the source and
+ * target directories, and the sb->s_vfs_rename_mutex if they
+ * differ. See lock_rename().
*/
static void __d_move(struct dentry *dentry, struct dentry *target,
bool exchange)
@@ -2793,14 +2829,17 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
spin_unlock(&dentry->d_lock);
}

-/*
- * d_move - move a dentry
+/**
+ * d_move() - Move a dentry.
* @dentry: entry to move
* @target: new dentry
*
* Update the dcache to reflect the move of a file name. Negative
- * dcache entries should not be moved in this way. See the locking
- * requirements for __d_move.
+ * dcache entries should not be moved in this way.
+ *
+ * Context: Caller must hold rename_lock, the i_mutex of the source and
+ * target directories, and the sb->s_vfs_rename_mutex if they
+ * differ. See lock_rename().
*/
void d_move(struct dentry *dentry, struct dentry *target)
{
@@ -2810,8 +2849,8 @@ void d_move(struct dentry *dentry, struct dentry *target)
}
EXPORT_SYMBOL(d_move);

-/*
- * d_exchange - exchange two dentries
+/**
+ * d_exchange() - Exchange two dentries.
* @dentry1: first dentry
* @dentry2: second dentry
*/
@@ -2830,12 +2869,12 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2)
}

/**
- * d_ancestor - search for an ancestor
+ * d_ancestor() - Search for an ancestor.
* @p1: ancestor dentry
* @p2: child dentry
*
- * Returns the ancestor dentry of p2 which is a child of p1, if p1 is
- * an ancestor of p2, else NULL.
+ * Return: The ancestor dentry of p2 which is a child of p1, if p1 is
+ * an ancestor of p2, else %NULL.
*/
struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2)
{
@@ -2887,13 +2926,13 @@ static int __d_unalias(struct inode *inode,
}

/**
- * d_splice_alias - splice a disconnected dentry into the tree if one exists
+ * d_splice_alias() - Splice a disconnected dentry into the tree if one exists.
* @inode: the inode which may have a disconnected dentry
* @dentry: a negative dentry which we want to point to the inode.
*
- * If inode is a directory and has an IS_ROOT alias, then d_move that in
- * place of the given dentry and return it, else simply d_add the inode
- * to the dentry and return NULL.
+ * If inode is a directory and has an IS_ROOT alias, then d_move() that in
+ * place of the given dentry and return it, else simply d_add() the inode
+ * to the dentry and return %NULL.
*
* If a non-IS_ROOT directory is found, the filesystem is corrupt, and
* we should error out: directories can't have multiple aliases.
@@ -2901,7 +2940,7 @@ static int __d_unalias(struct inode *inode,
* This is needed in the lookup routine of any filesystem that is exportable
* (via knfsd) so that we can build dcache paths to directories effectively.
*
- * If a dentry was found and moved, then it is returned. Otherwise NULL
+ * If a dentry was found and moved, then it is returned. Otherwise %NULL
* is returned. This matches the expected return value of ->lookup.
*
* Cluster filesystems may call this function with a negative, hashed dentry.
@@ -2971,11 +3010,11 @@ EXPORT_SYMBOL(d_splice_alias);
* @new_dentry: new dentry
* @old_dentry: old dentry
*
- * Returns true if new_dentry is a subdirectory of the parent (at any depth).
- * Returns false otherwise.
- * Caller must ensure that "new_dentry" is pinned before calling is_subdir()
+ * Return: True if new_dentry is a subdirectory of the parent (at any
+ * depth). False otherwise.
+ * Context: Caller must ensure that "new_dentry" is pinned before
+ * calling is_subdir().
*/
-
bool is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
{
bool result;
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 862aefe5a10a..0643c5127e1a 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -296,12 +296,14 @@ extern char *dentry_path(struct dentry *, char *, int);
/* Allocation counts.. */

/**
- * dget, dget_dlock - get a reference to a dentry
- * @dentry: dentry to get a reference to
+ * dget_dlock() - Get a reference to a dentry.
+ * @dentry: The dentry to get a reference to.
*
- * Given a dentry or %NULL pointer increment the reference count
- * if appropriate and return the dentry. A dentry will not be
- * destroyed when it has references.
+ * Given a dentry or %NULL pointer increment the reference count if
+ * appropriate. A dentry will not be destroyed when it has references.
+ *
+ * Context: Caller must hold the dentry->d_lock.
+ * Return: The dentry.
*/
static inline struct dentry *dget_dlock(struct dentry *dentry)
{
@@ -310,6 +312,16 @@ static inline struct dentry *dget_dlock(struct dentry *dentry)
return dentry;
}

+/**
+ * dget() - Get a reference to a dentry.
+ * @dentry: The dentry to get a reference to.
+ *
+ * Given a dentry or %NULL pointer increment the reference count if
+ * appropriate. A dentry will not be destroyed when it has references.
+ *
+ * Context: Takes the dentry->d_lock.
+ * Return: The dentry.
+ */
static inline struct dentry *dget(struct dentry *dentry)
{
if (dentry)
@@ -320,12 +332,11 @@ static inline struct dentry *dget(struct dentry *dentry)
extern struct dentry *dget_parent(struct dentry *dentry);

/**
- * d_unhashed - is dentry hashed
- * @dentry: entry to check
+ * d_unhashed() - Is dentry unhashed.
+ * @dentry: The dentry to check.
*
- * Returns true if the dentry passed is not currently hashed.
+ * Return: True if the dentry passed is not currently hashed.
*/
-
static inline int d_unhashed(const struct dentry *dentry)
{
return hlist_bl_unhashed(&dentry->d_hash);
@@ -499,7 +510,7 @@ static inline unsigned long vfs_pressure_ratio(unsigned long val)
}

/**
- * d_inode - Get the actual inode of this dentry
+ * d_inode() - Get the actual inode of this dentry.
* @dentry: The dentry to query
*
* This is the helper normal filesystems should use to get at their own inodes
@@ -511,7 +522,7 @@ static inline struct inode *d_inode(const struct dentry *dentry)
}

/**
- * d_inode_rcu - Get the actual inode of this dentry with READ_ONCE()
+ * d_inode_rcu() - Get the actual inode of this dentry with READ_ONCE().
* @dentry: The dentry to query
*
* This is the helper normal filesystems should use to get at their own inodes
@@ -523,7 +534,7 @@ static inline struct inode *d_inode_rcu(const struct dentry *dentry)
}

/**
- * d_backing_inode - Get upper or lower inode we should be using
+ * d_backing_inode() - Get upper or lower inode we should be using.
* @upper: The upper layer
*
* This is the helper that should be used to get at the inode that will be used
@@ -540,7 +551,7 @@ static inline struct inode *d_backing_inode(const struct dentry *upper)
}

/**
- * d_backing_dentry - Get upper or lower dentry we should be using
+ * d_backing_dentry() - Get upper or lower dentry we should be using.
* @upper: The upper layer
*
* This is the helper that should be used to get the dentry of the inode that
@@ -555,9 +566,9 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper)
}

/**
- * d_real - Return the real dentry
+ * d_real() - Return the real dentry.
* @dentry: the dentry to query
- * @inode: inode to select the dentry from multiple layers (can be NULL)
+ * @inode: inode to select the dentry from multiple layers (can be %NULL)
*
* If dentry is on a union/overlay, then return the underlying, real dentry.
* Otherwise return the dentry itself.
@@ -574,7 +585,7 @@ static inline struct dentry *d_real(struct dentry *dentry,
}

/**
- * d_real_inode - Return the real inode
+ * d_real_inode() - Return the real inode.
* @dentry: The dentry to query
*
* If dentry is on a union/overlay, then return the underlying, real inode.
--
2.21.0


2019-03-27 05:22:10

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 16/24] docs: filesystems: vfs: Use uniform space after period.

Currently sometimes document has a single space after a period and
sometimes it has double. Whichever we use it should be uniform.

Use double space after period, be uniform.

Tested-by: Randy Dunlap <[email protected]>
Signed-off-by: Tobin C. Harding <[email protected]>
---
Documentation/filesystems/vfs.txt | 246 +++++++++++++++---------------
1 file changed, 123 insertions(+), 123 deletions(-)

diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 75b47768c806..62a6ad52b191 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -16,12 +16,12 @@ Introduction

The Virtual File System (also known as the Virtual Filesystem Switch)
is the software layer in the kernel that provides the filesystem
-interface to userspace programs. It also provides an abstraction
+interface to userspace programs. It also provides an abstraction
within the kernel which allows different filesystem implementations to
coexist.

VFS system calls open(2), stat(2), read(2), write(2), chmod(2) and so
-on are called from a process context. Filesystem locking is described
+on are called from a process context. Filesystem locking is described
in the document Documentation/filesystems/Locking.


@@ -29,37 +29,37 @@ Directory Entry Cache (dcache)
------------------------------

The VFS implements the open(2), stat(2), chmod(2), and similar system
-calls. The pathname argument that is passed to them is used by the VFS
+calls. The pathname argument that is passed to them is used by the VFS
to search through the directory entry cache (also known as the dentry
-cache or dcache). This provides a very fast look-up mechanism to
-translate a pathname (filename) into a specific dentry. Dentries live
+cache or dcache). This provides a very fast look-up mechanism to
+translate a pathname (filename) into a specific dentry. Dentries live
in RAM and are never saved to disc: they exist only for performance.

-The dentry cache is meant to be a view into your entire filespace. As
+The dentry cache is meant to be a view into your entire filespace. As
most computers cannot fit all dentries in the RAM at the same time,
-some bits of the cache are missing. In order to resolve your pathname
+some bits of the cache are missing. In order to resolve your pathname
into a dentry, the VFS may have to resort to creating dentries along
-the way, and then loading the inode. This is done by looking up the
+the way, and then loading the inode. This is done by looking up the
inode.


The Inode Object
----------------

-An individual dentry usually has a pointer to an inode. Inodes are
+An individual dentry usually has a pointer to an inode. Inodes are
filesystem objects such as regular files, directories, FIFOs and other
beasts. They live either on the disc (for block device filesystems)
-or in the memory (for pseudo filesystems). Inodes that live on the
+or in the memory (for pseudo filesystems). Inodes that live on the
disc are copied into the memory when required and changes to the inode
-are written back to disc. A single inode can be pointed to by multiple
+are written back to disc. A single inode can be pointed to by multiple
dentries (hard links, for example, do this).

To look up an inode requires that the VFS calls the lookup() method of
-the parent directory inode. This method is installed by the specific
-filesystem implementation that the inode lives in. Once the VFS has
+the parent directory inode. This method is installed by the specific
+filesystem implementation that the inode lives in. Once the VFS has
the required dentry (and hence the inode), we can do all those boring
things like open(2) the file, or stat(2) it to peek at the inode
-data. The stat(2) operation is fairly simple: once the VFS has the
+data. The stat(2) operation is fairly simple: once the VFS has the
dentry, it peeks at the inode data and passes some of it back to
userspace.

@@ -69,17 +69,17 @@ The File Object

Opening a file requires another operation: allocation of a file
structure (this is the kernel-side implementation of file
-descriptors). The freshly allocated file structure is initialized with
+descriptors). The freshly allocated file structure is initialized with
a pointer to the dentry and a set of file operation member functions.
-These are taken from the inode data. The open() file method is then
-called so the specific filesystem implementation can do its work. You
-can see that this is another switch performed by the VFS. The file
+These are taken from the inode data. The open() file method is then
+called so the specific filesystem implementation can do its work. You
+can see that this is another switch performed by the VFS. The file
structure is placed into the file descriptor table for the process.

Reading, writing and closing files (and other assorted VFS operations)
is done by using the userspace file descriptor to grab the appropriate
file structure, and then calling the required file structure method to
-do whatever is required. For as long as the file is open, it keeps the
+do whatever is required. For as long as the file is open, it keeps the
dentry in use, which in turn means that the VFS inode is still in use.


@@ -94,7 +94,7 @@ functions:
extern int register_filesystem(struct file_system_type *);
extern int unregister_filesystem(struct file_system_type *);

-The passed struct file_system_type describes your filesystem. When a
+The passed struct file_system_type describes your filesystem. When a
request is made to mount a filesystem onto a directory in your namespace,
the VFS will call the appropriate mount() method for the specific
filesystem. New vfsmount referring to the tree returned by ->mount()
@@ -108,7 +108,7 @@ file /proc/filesystems.
struct file_system_type
-----------------------

-This describes the filesystem. As of kernel 2.6.39, the following
+This describes the filesystem. As of kernel 2.6.39, the following
members are defined:

struct file_system_type {
@@ -170,12 +170,12 @@ point of view is a reference to dentry at the root of (sub)tree to
be attached; creation of new superblock is a common side effect.

The most interesting member of the superblock structure that the
-mount() method fills in is the "s_op" field. This is a pointer to
+mount() method fills in is the "s_op" field. This is a pointer to
a "struct super_operations" which describes the next level of the
filesystem implementation.

Usually, a filesystem uses one of the generic mount() implementations
-and provides a fill_super() callback instead. The generic variants are:
+and provides a fill_super() callback instead. The generic variants are:

mount_bdev: mount a filesystem residing on a block device

@@ -186,7 +186,7 @@ and provides a fill_super() callback instead. The generic variants are:

A fill_super() callback implementation has the following arguments:

- struct super_block *sb: the superblock structure. The callback
+ struct super_block *sb: the superblock structure. The callback
must initialize this properly.

void *data: arbitrary mount options, usually comes as an ASCII
@@ -205,7 +205,7 @@ struct super_operations
-----------------------

This describes how the VFS can manipulate the superblock of your
-filesystem. As of kernel 2.6.22, the following members are defined:
+filesystem. As of kernel 2.6.22, the following members are defined:

struct super_operations {
struct inode *(*alloc_inode)(struct super_block *sb);
@@ -233,7 +233,7 @@ struct super_operations {
};

All methods are called without any locks being held, unless otherwise
-noted. This means that most methods can block safely. All methods are
+noted. This means that most methods can block safely. All methods are
only called from a process context (i.e. not from an interrupt handler
or bottom half).

@@ -270,11 +270,11 @@ or bottom half).
delete_inode: called when the VFS wants to delete an inode

put_super: called when the VFS wishes to free the superblock
- (i.e. unmount). This is called with the superblock lock held
+ (i.e. unmount). This is called with the superblock lock held

sync_fs: called when VFS is writing out all dirty data associated with
- a superblock. The second parameter indicates whether the method
- should wait until the write out has been completed. Optional.
+ a superblock. The second parameter indicates whether the method
+ should wait until the write out has been completed. Optional.

freeze_fs: called when VFS is locking a filesystem and
forcing it into a consistent state. This method is currently
@@ -285,10 +285,10 @@ or bottom half).

statfs: called when the VFS needs to get filesystem statistics.

- remount_fs: called when the filesystem is remounted. This is called
+ remount_fs: called when the filesystem is remounted. This is called
with the kernel lock held

- clear_inode: called then the VFS clears the inode. Optional
+ clear_inode: called then the VFS clears the inode. Optional

umount_begin: called when the VFS is unmounting a filesystem.

@@ -309,17 +309,17 @@ or bottom half).
implement ->nr_cached_objects for it to be called correctly.

We can't do anything with any errors that the filesystem might
- encountered, hence the void return type. This will never be called if
+ encountered, hence the void return type. This will never be called if
the VM is trying to reclaim under GFP_NOFS conditions, hence this
method does not need to handle that situation itself.

Implementations must include conditional reschedule calls inside any
- scanning loop that is done. This allows the VFS to determine
+ scanning loop that is done. This allows the VFS to determine
appropriate scan batch sizes without having to worry about whether
implementations will cause holdoff problems due to large scan batch
sizes.

-Whoever sets up the inode is responsible for filling in the "i_op" field. This
+Whoever sets up the inode is responsible for filling in the "i_op" field. This
is a pointer to a "struct inode_operations" which describes the methods that
can be performed on individual inodes.

@@ -363,7 +363,7 @@ struct inode_operations
-----------------------

This describes how the VFS can manipulate an inode in your
-filesystem. As of kernel 2.6.22, the following members are defined:
+filesystem. As of kernel 2.6.22, the following members are defined:

struct inode_operations {
int (*create) (struct inode *,struct dentry *, umode_t, bool);
@@ -393,19 +393,19 @@ struct inode_operations {
Again, all methods are called without any locks being held, unless
otherwise noted.

- create: called by the open(2) and creat(2) system calls. Only
- required if you want to support regular files. The dentry you
+ create: called by the open(2) and creat(2) system calls. Only
+ required if you want to support regular files. The dentry you
get should not have an inode (i.e. it should be a negative
- dentry). Here you will probably call d_instantiate() with the
+ dentry). Here you will probably call d_instantiate() with the
dentry and the newly created inode

lookup: called when the VFS needs to look up an inode in a parent
- directory. The name to look for is found in the dentry. This
+ directory. The name to look for is found in the dentry. This
method must call d_add() to insert the found inode into the
- dentry. The "i_count" field in the inode structure should be
- incremented. If the named inode does not exist a NULL inode
+ dentry. The "i_count" field in the inode structure should be
+ incremented. If the named inode does not exist a NULL inode
should be inserted into the dentry (this is called a negative
- dentry). Returning an error code from this routine must only
+ dentry). Returning an error code from this routine must only
be done on a real error, otherwise creating inodes with system
calls like create(2), mknod(2), mkdir(2) and so on will fail.
If you wish to overload the dentry methods then you should
@@ -413,27 +413,27 @@ otherwise noted.
to a struct "dentry_operations".
This method is called with the directory inode semaphore held

- link: called by the link(2) system call. Only required if you want
- to support hard links. You will probably need to call
+ link: called by the link(2) system call. Only required if you want
+ to support hard links. You will probably need to call
d_instantiate() just as you would in the create() method

- unlink: called by the unlink(2) system call. Only required if you
+ unlink: called by the unlink(2) system call. Only required if you
want to support deleting inodes

- symlink: called by the symlink(2) system call. Only required if you
- want to support symlinks. You will probably need to call
+ symlink: called by the symlink(2) system call. Only required if you
+ want to support symlinks. You will probably need to call
d_instantiate() just as you would in the create() method

- mkdir: called by the mkdir(2) system call. Only required if you want
- to support creating subdirectories. You will probably need to
+ mkdir: called by the mkdir(2) system call. Only required if you want
+ to support creating subdirectories. You will probably need to
call d_instantiate() just as you would in the create() method

- rmdir: called by the rmdir(2) system call. Only required if you want
+ rmdir: called by the rmdir(2) system call. Only required if you want
to support deleting subdirectories

mknod: called by the mknod(2) system call to create a device (char,
- block) inode or a named pipe (FIFO) or socket. Only required
- if you want to support creating these types of inodes. You
+ block) inode or a named pipe (FIFO) or socket. Only required
+ if you want to support creating these types of inodes. You
will probably need to call d_instantiate() just as you would
in the create() method

@@ -474,21 +474,21 @@ otherwise noted.
permission: called by the VFS to check for access rights on a POSIX-like
filesystem.

- May be called in rcu-walk mode (mask & MAY_NOT_BLOCK). If in rcu-walk
- mode, the filesystem must check the permission without blocking or
+ May be called in rcu-walk mode (mask & MAY_NOT_BLOCK). If in rcu-walk
+ mode, the filesystem must check the permission without blocking or
storing to the inode.

If a situation is encountered that rcu-walk cannot handle, return
-ECHILD and it will be called again in ref-walk mode.

- setattr: called by the VFS to set attributes for a file. This method
+ setattr: called by the VFS to set attributes for a file. This method
is called by chmod(2) and related system calls.

- getattr: called by the VFS to get attributes of a file. This method
+ getattr: called by the VFS to get attributes of a file. This method
is called by stat(2) and related system calls.

listxattr: called by the VFS to list all extended attributes for a
- given file. This method is called by the listxattr(2) system call.
+ given file. This method is called by the listxattr(2) system call.

update_time: called by the VFS to update a specific time or the i_version of
an inode. If this is not defined the VFS will update the inode itself
@@ -526,7 +526,7 @@ The first can be used independently to the others. The VM can try to
either write dirty pages in order to clean them, or release clean
pages in order to reuse them. To do this it can call the ->writepage
method on dirty pages, and ->releasepage on clean pages with
-PagePrivate set. Clean pages without PagePrivate and with no external
+PagePrivate set. Clean pages without PagePrivate and with no external
references will be released without notice being given to the
address_space.

@@ -534,7 +534,7 @@ To achieve this functionality, pages need to be placed on an LRU with
lru_cache_add and mark_page_active needs to be called whenever the
page is used.

-Pages are normally kept in a radix tree index by ->index. This tree
+Pages are normally kept in a radix tree index by ->index. This tree
maintains information about the PG_Dirty and PG_Writeback status of
each page, so that pages with either of these flags can be found
quickly.
@@ -620,7 +620,7 @@ struct address_space_operations
-------------------------------

This describes how the VFS can manipulate mapping of a file to page cache in
-your filesystem. The following members are defined:
+your filesystem. The following members are defined:

struct address_space_operations {
int (*writepage)(struct page *page, struct writeback_control *wbc);
@@ -700,7 +700,7 @@ struct address_space_operations {
PAGECACHE_TAG_DIRTY tag in the radix tree.

readpages: called by the VM to read pages associated with the address_space
- object. This is essentially just a vector version of
+ object. This is essentially just a vector version of
readpage. Instead of just one page, several pages are
requested.
readpages is only used for read-ahead, so read errors are
@@ -708,7 +708,7 @@ struct address_space_operations {

write_begin:
Called by the generic buffered write code to ask the filesystem to
- prepare to write len bytes at the given offset in the file. The
+ prepare to write len bytes at the given offset in the file. The
address_space should check that the write will be able to complete,
by allocating space if necessary and doing any other internal
housekeeping. If the write will update parts of any basic-blocks on
@@ -731,7 +731,7 @@ struct address_space_operations {
which case write_end is not called.

write_end: After a successful write_begin, and data copy, write_end must
- be called. len is the original len passed to write_begin, and copied
+ be called. len is the original len passed to write_begin, and copied
is the amount that was able to be copied.

The filesystem must take care of unlocking the page and releasing it
@@ -741,7 +741,7 @@ struct address_space_operations {
that were able to be copied into pagecache.

bmap: called by the VFS to map a logical block offset within object to
- physical block number. This method is used by the FIBMAP
+ physical block number. This method is used by the FIBMAP
ioctl and for working with swap-files. To be able to swap to
a file, the file must have a stable mapping to a block
device. The swap system does not go through the filesystem
@@ -753,7 +753,7 @@ struct address_space_operations {
from the address space. This generally corresponds to either a
truncation, punch hole or a complete invalidation of the address
space (in the latter case 'offset' will always be 0 and 'length'
- will be PAGE_SIZE). Any private data associated with the page
+ will be PAGE_SIZE). Any private data associated with the page
should be updated to reflect this truncation. If offset is 0 and
length is PAGE_SIZE, then the private data should be released,
because the page must be able to be completely discarded. This may
@@ -763,7 +763,7 @@ struct address_space_operations {
releasepage: releasepage is called on PagePrivate pages to indicate
that the page should be freed if possible. ->releasepage
should remove any private data from the page and clear the
- PagePrivate flag. If releasepage() fails for some reason, it must
+ PagePrivate flag. If releasepage() fails for some reason, it must
indicate failure with a 0 return value.
releasepage() is used in two distinct though related cases. The
first is when the VM finds a clean page with no active users and
@@ -783,7 +783,7 @@ struct address_space_operations {

freepage: freepage is called once the page is no longer visible in
the page cache in order to allow the cleanup of any private
- data. Since it may be called by the memory reclaimer, it
+ data. Since it may be called by the memory reclaimer, it
should not assume that the original address_space mapping still
exists, and it should not block.

@@ -805,32 +805,32 @@ struct address_space_operations {

putback_page: Called by the VM when isolated page's migration fails.

- launder_page: Called before freeing a page - it writes back the dirty page. To
+ launder_page: Called before freeing a page - it writes back the dirty page. To
prevent redirtying the page, it is kept locked during the whole
operation.

is_partially_uptodate: Called by the VM when reading a file through the
- pagecache when the underlying blocksize != pagesize. If the required
+ pagecache when the underlying blocksize != pagesize. If the required
block is up to date then the read can complete without needing the IO
to bring the whole page up to date.

is_dirty_writeback: Called by the VM when attempting to reclaim a page.
The VM uses dirty and writeback information to determine if it needs
- to stall to allow flushers a chance to complete some IO. Ordinarily
+ to stall to allow flushers a chance to complete some IO. Ordinarily
it can use PageDirty and PageWriteback but some filesystems have
more complex state (unstable pages in NFS prevent reclaim) or
- do not set those flags due to locking problems. This callback
+ do not set those flags due to locking problems. This callback
allows a filesystem to indicate to the VM if a page should be
treated as dirty or writeback for the purposes of stalling.

error_remove_page: normally set to generic_error_remove_page if truncation
- is ok for this address space. Used for memory failure handling.
+ is ok for this address space. Used for memory failure handling.
Setting this implies you deal with pages going away under you,
unless you have them locked or reference counts increased.

swap_activate: Called when swapon is used on a file to allocate
space if necessary and pin the block lookup information in
- memory. A return value of zero indicates success,
+ memory. A return value of zero indicates success,
in which case this file can be used to back swapspace.

swap_deactivate: Called during swapoff on files where swap_activate
@@ -840,14 +840,14 @@ struct address_space_operations {
The File Object
===============

-A file object represents a file opened by a process. This is also known
+A file object represents a file opened by a process. This is also known
as an "open file description" in POSIX parlance.


struct file_operations
----------------------

-This describes how the VFS can manipulate an open file. As of kernel
+This describes how the VFS can manipulate an open file. As of kernel
4.18, the following members are defined:

struct file_operations {
@@ -909,7 +909,7 @@ otherwise noted.

poll: called by the VFS when a process wants to check if there is
activity on this file and (optionally) go to sleep until there
- is activity. Called by the select(2) and poll(2) system calls
+ is activity. Called by the select(2) and poll(2) system calls

unlocked_ioctl: called by the ioctl(2) system call.

@@ -918,13 +918,13 @@ otherwise noted.

mmap: called by the mmap(2) system call

- open: called by the VFS when an inode should be opened. When the VFS
- opens a file, it creates a new "struct file". It then calls the
- open method for the newly allocated file structure. You might
+ open: called by the VFS when an inode should be opened. When the VFS
+ opens a file, it creates a new "struct file". It then calls the
+ open method for the newly allocated file structure. You might
think that the open method really belongs in
- "struct inode_operations", and you may be right. I think it's
+ "struct inode_operations", and you may be right. I think it's
done the way it is because it makes filesystems simpler to
- implement. The open() method is a good place to initialize the
+ implement. The open() method is a good place to initialize the
"private_data" member in the file structure if you want to point
to a device structure

@@ -932,7 +932,7 @@ otherwise noted.

release: called when the last reference to an open file is closed

- fsync: called by the fsync(2) system call. Also see the section above
+ fsync: called by the fsync(2) system call. Also see the section above
entitled "Handling errors during writeback".

fasync: called by the fcntl(2) system call when asynchronous
@@ -947,13 +947,13 @@ otherwise noted.

flock: called by the flock(2) system call

- splice_write: called by the VFS to splice data from a pipe to a file. This
+ splice_write: called by the VFS to splice data from a pipe to a file. This
method is used by the splice(2) system call

- splice_read: called by the VFS to splice data from file to a pipe. This
+ splice_read: called by the VFS to splice data from file to a pipe. This
method is used by the splice(2) system call

- setlease: called by the VFS to set or release a file lock lease. setlease
+ setlease: called by the VFS to set or release a file lock lease. setlease
implementations should call generic_setlease to record or remove
the lease in the inode after setting it.

@@ -977,12 +977,12 @@ otherwise noted.
fadvise: possibly called by the fadvise64() system call.

Note that the file operations are implemented by the specific
-filesystem in which the inode resides. When opening a device node
+filesystem in which the inode resides. When opening a device node
(character or block special) most filesystems will call special
support routines in the VFS which will locate the required device
-driver information. These support routines replace the filesystem file
+driver information. These support routines replace the filesystem file
operations with those for the device driver, and then proceed to call
-the new open() method for the file. This is how opening a device file
+the new open() method for the file. This is how opening a device file
in the filesystem eventually ends up calling the device driver open()
method.

@@ -995,10 +995,10 @@ struct dentry_operations
------------------------

This describes how a filesystem can overload the standard dentry
-operations. Dentries and the dcache are the domain of the VFS and the
-individual filesystem implementations. Device drivers have no business
-here. These methods may be set to NULL, as they are either optional or
-the VFS uses a default. As of kernel 2.6.22, the following members are
+operations. Dentries and the dcache are the domain of the VFS and the
+individual filesystem implementations. Device drivers have no business
+here. These methods may be set to NULL, as they are either optional or
+the VFS uses a default. As of kernel 2.6.22, the following members are
defined:

struct dentry_operations {
@@ -1017,10 +1017,10 @@ struct dentry_operations {
struct dentry *(*d_real)(struct dentry *, const struct inode *);
};

- d_revalidate: called when the VFS needs to revalidate a dentry. This
+ d_revalidate: called when the VFS needs to revalidate a dentry. This
is called whenever a name look-up finds a dentry in the
- dcache. Most local filesystems leave this as NULL, because all their
- dentries in the dcache are valid. Network filesystems are different
+ dcache. Most local filesystems leave this as NULL, because all their
+ dentries in the dcache are valid. Network filesystems are different
since things can change on the server without the client necessarily
being aware of it.

@@ -1038,11 +1038,11 @@ struct dentry_operations {

d_weak_revalidate: called when the VFS needs to revalidate a "jumped" dentry.
This is called when a path-walk ends at dentry that was not acquired by
- doing a lookup in the parent directory. This includes "/", "." and "..",
+ doing a lookup in the parent directory. This includes "/", "." and "..",
as well as procfs-style symlinks and mountpoint traversal.

In this case, we are less concerned with whether the dentry is still
- fully correct, but rather that the inode is still valid. As with
+ fully correct, but rather that the inode is still valid. As with
d_revalidate, most local filesystems will set this to NULL since their
dcache entries are always valid.

@@ -1050,17 +1050,17 @@ struct dentry_operations {

d_weak_revalidate is only called after leaving rcu-walk mode.

- d_hash: called when the VFS adds a dentry to the hash table. The first
+ d_hash: called when the VFS adds a dentry to the hash table. The first
dentry passed to d_hash is the parent directory that the name is
to be hashed into.

Same locking and synchronisation rules as d_compare regarding
what is safe to dereference etc.

- d_compare: called to compare a dentry name with a given name. The first
+ d_compare: called to compare a dentry name with a given name. The first
dentry is the parent of the dentry to be compared, the second is
- the child dentry. len and name string are properties of the dentry
- to be compared. qstr is the name to compare it with.
+ the child dentry. len and name string are properties of the dentry
+ to be compared. qstr is the name to compare it with.

Must be constant and idempotent, and should not take locks if
possible, and should not or store into the dentry.
@@ -1075,9 +1075,9 @@ struct dentry_operations {
"rcu-walk", ie. without any locks or references on things.

d_delete: called when the last reference to a dentry is dropped and the
- dcache is deciding whether or not to cache it. Return 1 to delete
- immediately, or 0 to cache the dentry. Default is NULL which means to
- always cache a reachable dentry. d_delete must be constant and
+ dcache is deciding whether or not to cache it. Return 1 to delete
+ immediately, or 0 to cache the dentry. Default is NULL which means to
+ always cache a reachable dentry. d_delete must be constant and
idempotent.

d_init: called when a dentry is allocated
@@ -1085,19 +1085,19 @@ struct dentry_operations {
d_release: called when a dentry is really deallocated

d_iput: called when a dentry loses its inode (just prior to its
- being deallocated). The default when this is NULL is that the
- VFS calls iput(). If you define this method, you must call
+ being deallocated). The default when this is NULL is that the
+ VFS calls iput(). If you define this method, you must call
iput() yourself

d_dname: called when the pathname of a dentry should be generated.
Useful for some pseudo filesystems (sockfs, pipefs, ...) to delay
- pathname generation. (Instead of doing it when dentry is created,
- it's done only when the path is needed.). Real filesystems probably
+ pathname generation. (Instead of doing it when dentry is created,
+ it's done only when the path is needed.). Real filesystems probably
dont want to use it, because their dentries are present in global
- dcache hash, so their hash should be an invariant. As no lock is
+ dcache hash, so their hash should be an invariant. As no lock is
held, d_dname() should not try to modify the dentry itself, unless
- appropriate SMP safety is used. CAUTION : d_path() logic is quite
- tricky. The correct way to return for example "Hello" is to put it
+ appropriate SMP safety is used. CAUTION : d_path() logic is quite
+ tricky. The correct way to return for example "Hello" is to put it
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.

@@ -1159,7 +1159,7 @@ struct dentry_operations {
With NULL inode the topmost real underlying dentry is returned.

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
directory.


@@ -1172,36 +1172,36 @@ manipulate dentries:
dget: open a new handle for an existing dentry (this just increments
the usage count)

- dput: close a handle for a dentry (decrements the usage count). If
+ dput: close a handle for a dentry (decrements the usage count). If
the usage count drops to 0, and the dentry is still in its
parent's hash, the "d_delete" method is called to check whether
- it should be cached. If it should not be cached, or if the dentry
- is not hashed, it is deleted. Otherwise cached dentries are put
+ it should be cached. If it should not be cached, or if the dentry
+ is not hashed, it is deleted. Otherwise cached dentries are put
into an LRU list to be reclaimed on memory shortage.

- d_drop: this unhashes a dentry from its parents hash list. A
+ d_drop: this unhashes a dentry from its parents hash list. A
subsequent call to dput() will deallocate the dentry if its
usage count drops to 0

- d_delete: delete a dentry. If there are no other open references to
+ d_delete: delete a dentry. If there are no other open references to
the dentry then the dentry is turned into a negative dentry
- (the d_iput() method is called). If there are other
+ (the d_iput() method is called). If there are other
references, then d_drop() is called instead

d_add: add a dentry to its parents hash list and then calls
d_instantiate()

d_instantiate: add a dentry to the alias hash list for the inode and
- updates the "d_inode" member. The "i_count" member in the
- inode structure should be set/incremented. If the inode
+ updates the "d_inode" member. The "i_count" member in the
+ inode structure should be set/incremented. If the inode
pointer is NULL, the dentry is called a "negative
- dentry". This function is commonly called when an inode is
+ dentry". This function is commonly called when an inode is
created for an existing negative dentry

d_lookup: look up a dentry given its parent and path name component
It looks up the child of that given name from the dcache
- hash table. If it is found, the reference count is incremented
- and the dentry is returned. The caller must use dput()
+ hash table. If it is found, the reference count is incremented
+ and the dentry is returned. The caller must use dput()
to free the dentry when it finishes using it.

Mount Options
--
2.21.0


2019-03-27 05:22:27

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 21/24] docs: filesystems: vfs: Fix pre-amble indentation

Currently file pre-amble contains custom indentation. RST is not going
to like this, lets left-align the text. Put the copyright notices in a
list in preparation for converting document to RST.

Tested-by: Randy Dunlap <[email protected]>
Signed-off-by: Tobin C. Harding <[email protected]>
---
Documentation/filesystems/vfs.txt | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index dcc1f66932e7..e5c877e817c3 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -4,12 +4,12 @@
Overview of the Linux Virtual File System
=========================================

- Original author: Richard Gooch <[email protected]>
+Original author: Richard Gooch <[email protected]>

- Last updated on June 24, 2007.
+Last updated on June 24, 2007.

- Copyright (C) 1999 Richard Gooch
- Copyright (C) 2005 Pekka Enberg
+- Copyright (C) 1999 Richard Gooch
+- Copyright (C) 2005 Pekka Enberg


Introduction
--
2.21.0


2019-03-27 05:22:31

by Tobin C. Harding

[permalink] [raw]
Subject: [PATCH v3 20/24] docs: filesystems: vfs: Use SPDX identifier

Currently the licence is indicated via a custom string. We have SPDX
license identifiers now for this task.

Use SPDX license identifier matching current license string.

Tested-by: Randy Dunlap <[email protected]>
Signed-off-by: Tobin C. Harding <[email protected]>
---
Documentation/filesystems/vfs.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 0bc45c3a33db..dcc1f66932e7 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -1,3 +1,5 @@
+.. SPDX-License-Identifier: GPL-2.0
+
=========================================
Overview of the Linux Virtual File System
=========================================
@@ -9,8 +11,6 @@ Overview of the Linux Virtual File System
Copyright (C) 1999 Richard Gooch
Copyright (C) 2005 Pekka Enberg

- This file is released under the GPLv2.
-

Introduction
============
--
2.21.0


2019-03-27 05:25:28

by Joe Perches

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Wed, 2019-03-27 at 16:16 +1100, Tobin C. Harding wrote:
> Hi Al,
>
> This series converts the VFS file Documentation/filesystems/vfs.txt to
> reStructuredText format.

Perhaps add a MAINTAINERS entry too.

> Please consider taking this series through
> your tree as apposed to Jon's tree because this set makes a fair amount
> of changes to VFS files (and also the VFS tree and docs tree are out of
> sync right now with the recent work by Mauro and Neil).



2019-03-27 06:28:12

by Tobin C. Harding

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Tue, Mar 26, 2019 at 10:24:37PM -0700, Joe Perches wrote:
> On Wed, 2019-03-27 at 16:16 +1100, Tobin C. Harding wrote:
> > Hi Al,
> >
> > This series converts the VFS file Documentation/filesystems/vfs.txt to
> > reStructuredText format.
>
> Perhaps add a MAINTAINERS entry too.

Checkpatch suggested that to me, I didn't think it was polite to put
Al's name on it without him first seeing it :) I can certainly add it
to MAINTAINERS for the next version if you want me to Al.

thanks,
Tobin.

2019-04-01 05:44:31

by Mukesh Ojha

[permalink] [raw]
Subject: Re: [PATCH v3 20/24] docs: filesystems: vfs: Use SPDX identifier


On 3/27/2019 10:47 AM, Tobin C. Harding wrote:
> Currently the licence is indicated via a custom string. We have SPDX
> license identifiers now for this task.
>
> Use SPDX license identifier matching current license string.
>
> Tested-by: Randy Dunlap <[email protected]>
> Signed-off-by: Tobin C. Harding <[email protected]>
Reviewed-by: Mukesh Ojha <[email protected]>

Cheers,
-Mukesh
> ---
> Documentation/filesystems/vfs.txt | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
> index 0bc45c3a33db..dcc1f66932e7 100644
> --- a/Documentation/filesystems/vfs.txt
> +++ b/Documentation/filesystems/vfs.txt
> @@ -1,3 +1,5 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> =========================================
> Overview of the Linux Virtual File System
> =========================================
> @@ -9,8 +11,6 @@ Overview of the Linux Virtual File System
> Copyright (C) 1999 Richard Gooch
> Copyright (C) 2005 Pekka Enberg
>
> - This file is released under the GPLv2.
> -
>
> Introduction
> ============

2019-04-02 16:03:42

by Jonathan Corbet

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Wed, 27 Mar 2019 16:16:53 +1100
"Tobin C. Harding" <[email protected]> wrote:

> Hi Al,
>
> This series converts the VFS file Documentation/filesystems/vfs.txt to
> reStructuredText format. Please consider taking this series through
> your tree as apposed to Jon's tree because this set makes a fair amount
> of changes to VFS files (and also the VFS tree and docs tree are out of
> sync right now with the recent work by Mauro and Neil).

Al, do you have any thoughts on how you want to handle this? I was about
to apply Jeff Layton's vfs.txt update, but would rather not create
conflicts unnecessarily. Let me know if you'd like me to pick this work
up.

Thanks,

jon

2019-04-02 18:26:07

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Tue, Apr 02, 2019 at 09:49:34AM -0600, Jonathan Corbet wrote:
> On Wed, 27 Mar 2019 16:16:53 +1100
> "Tobin C. Harding" <[email protected]> wrote:
>
> > Hi Al,
> >
> > This series converts the VFS file Documentation/filesystems/vfs.txt to
> > reStructuredText format. Please consider taking this series through
> > your tree as apposed to Jon's tree because this set makes a fair amount
> > of changes to VFS files (and also the VFS tree and docs tree are out of
> > sync right now with the recent work by Mauro and Neil).
>
> Al, do you have any thoughts on how you want to handle this? I was about
> to apply Jeff Layton's vfs.txt update, but would rather not create
> conflicts unnecessarily. Let me know if you'd like me to pick this work
> up.

Frankly, I would rather see that file be eventually replaced by something
saner, and I'm not talking about the format. Re Jeff's patch...

+ d_prune: called prior to pruning (i.e. unhashing and killing) a hashed
+ dentry from the dcache.

is flat-out misguiding. First of all, it *is* called for unhashed dentries,
TYVM. Furthermore, "prior to" is far too vague.

What really happens: there's a point in state diagram for dentries where
we commit to destroying a dentry and start taking it apart. That transition
happens with ->d_lock of dentry, ->i_lock of its inode (if any) and
->d_lock of the parent (again, if any) held; ->d_prune() is the last
chance for filesystem to see the (now doomed) dentry still intact.

It doesn't matter whether it's hashed or not, etc. The locks held
are sufficient to stabilize pretty much everything[1] in dentry and
nothing is destroyed yet. The only apparent exception is ->d_count,
but that's not real - we are guaranteed that there had been no other
counted references to dentry at the decision point and that none
could've been added. So this "oh, it's not 0 now, it's gone negative
after lockref_mark_dead() the caller has just done" is a red herring.

->d_prune() must not drop/regain any of the locks held by caller.
It must _not_ free anything attached to dentry - that belongs
later in the shutdown sequence. If anything, I'm tempted to
make it take const struct dentry * as argument, just to make
that clear.

No new (counted) references can be acquired by that point;
lockless dcache lookup might find our dentry a match, but
result of such lookup is not going to be legitimized - it's
doomed to be thrown out as stale.

It really makes more sense as part of struct dentry lifecycle
description...

[1] in theory, ->d_time might be changed by overlapping lockless
call of ->d_revalidate(). Up to filesystem - VFS doesn't touch
that field (and AFAICS only NFS uses it these days).

2019-04-02 18:30:18

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Tue, Apr 02, 2019 at 05:48:24PM +0100, Al Viro wrote:

> ->d_prune() must not drop/regain any of the locks held by caller.
> It must _not_ free anything attached to dentry - that belongs
> later in the shutdown sequence. If anything, I'm tempted to
> make it take const struct dentry * as argument, just to make
> that clear.
>
> No new (counted) references can be acquired by that point;
> lockless dcache lookup might find our dentry a match, but
> result of such lookup is not going to be legitimized - it's
> doomed to be thrown out as stale.
>
> It really makes more sense as part of struct dentry lifecycle
> description...
>
> [1] in theory, ->d_time might be changed by overlapping lockless
> call of ->d_revalidate(). Up to filesystem - VFS doesn't touch
> that field (and AFAICS only NFS uses it these days).

One addition: ->d_prune() can overlap only with
* lockless ->d_hash()/->d_compare()
* lockless ->d_revalidate()
* lockless ->d_manage()
So it must not destroy anything used by those without an RCU
delay. The same goes for ->d_release() - both the list of
the things it can overlap with and requirements re RCU delays.

In-tree ->d_prune() instances are fine and so's the majority
of ->d_release(). However, autofs ->d_release() has something
that looks like an RCU use-after-free waiting to happen:
static void autofs_dentry_release(struct dentry *de)
{
struct autofs_info *ino = autofs_dentry_ino(de);
struct autofs_sb_info *sbi = autofs_sbi(de->d_sb);

pr_debug("releasing %p\n", de);

if (!ino)
return;
...
autofs_free_ino(ino);
}
with autofs_free_ino() being straight kfree(). Which means
that the lockless case of autofs_d_manage() can run into
autofs_dentry_ino(dentry) getting freed right under it.

And there we do have this reachable:
int autofs_expire_wait(const struct path *path, int rcu_walk)
{
struct dentry *dentry = path->dentry;
struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb);
struct autofs_info *ino = autofs_dentry_ino(dentry);
int status;
int state;

/* Block on any pending expire */
if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
return 0;
if (rcu_walk)
return -ECHILD;

the second check buggers off in lockless mode; the first one
can be done in lockless mode just fine, so AFAICS we do have
a problem there. Smells like we ought to make that kfree
in autofs_free_ino() RCU-delayed... Ian, have you, by any
chance, run into reports like that? Use-after-free or
oopsen in autofs_expire_wait() and friends, that is...

AFAICS, everything else is safe; however, looking through
those has turned up a fishy spot in ceph_d_revalidate():
} else if (d_really_is_positive(dentry) &&
ceph_snap(d_inode(dentry)) == CEPH_SNAPDIR) {
valid = 1;
Again, lockless ->d_revalidate() is called without anything
that would hold ->d_inode stable; the first part of the
condition does not guarantee that we won't run into
ceph_snap(NULL) and oops. Sure, compiler is almost certainly
not going to reload here, but we ought to use d_inode_rcu(dentry)
there.

Sigh...

2019-04-02 19:49:07

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Tue, Apr 02, 2019 at 06:54:01PM +0100, Al Viro wrote:
> static void autofs_dentry_release(struct dentry *de)
> {
> struct autofs_info *ino = autofs_dentry_ino(de);
> struct autofs_sb_info *sbi = autofs_sbi(de->d_sb);
>
> pr_debug("releasing %p\n", de);
>
> if (!ino)
> return;
> ...
> autofs_free_ino(ino);
> }
> with autofs_free_ino() being straight kfree(). Which means
> that the lockless case of autofs_d_manage() can run into
> autofs_dentry_ino(dentry) getting freed right under it.
>
> And there we do have this reachable:
> int autofs_expire_wait(const struct path *path, int rcu_walk)
> {
> struct dentry *dentry = path->dentry;
> struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb);
> struct autofs_info *ino = autofs_dentry_ino(dentry);
> int status;
> int state;
>
> /* Block on any pending expire */
> if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
> return 0;
> if (rcu_walk)
> return -ECHILD;
>
> the second check buggers off in lockless mode; the first one
> can be done in lockless mode just fine, so AFAICS we do have
> a problem there. Smells like we ought to make that kfree
> in autofs_free_ino() RCU-delayed... Ian, have you, by any
> chance, run into reports like that? Use-after-free or
> oopsen in autofs_expire_wait() and friends, that is...

Alternatively, we could clear ->d_fsdata in autofs_d_release()
under ->d_lock and have all potentially lockless users of
autofs_dentry_ino() take ->d_lock around messing with that.
I'd still prefer to do it as below, though. Ian, do you have
any objections against the following and, if you are OK with
it, which tree would you prefer it to go through?

autofs: fix use-after-free in lockless ->d_manage()

autofs_d_release() can overlap with lockless ->d_manage(),
ending up with autofs_dentry_ino() freed under the latter.
Make freeing autofs_info instances RCU-delayed...

Signed-off-by: Al Viro <[email protected]>
---
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 70c132acdab1..e1091312abe1 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -71,6 +71,7 @@ struct autofs_info {

kuid_t uid;
kgid_t gid;
+ struct rcu_head rcu;
};

#define AUTOFS_INF_EXPIRING (1<<0) /* dentry in the process of expiring */
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index 80597b88718b..fb0225f21c12 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -36,7 +36,7 @@ void autofs_clean_ino(struct autofs_info *ino)

void autofs_free_ino(struct autofs_info *ino)
{
- kfree(ino);
+ kfree_rcu(ino, rcu);
}

void autofs_kill_sb(struct super_block *sb)

2019-04-02 19:51:19

by Tobin C. Harding

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Tue, Apr 02, 2019 at 05:48:24PM +0100, Al Viro wrote:
> On Tue, Apr 02, 2019 at 09:49:34AM -0600, Jonathan Corbet wrote:
> > On Wed, 27 Mar 2019 16:16:53 +1100
> > "Tobin C. Harding" <[email protected]> wrote:
> >
> > > Hi Al,
> > >
> > > This series converts the VFS file Documentation/filesystems/vfs.txt to
> > > reStructuredText format. Please consider taking this series through
> > > your tree as apposed to Jon's tree because this set makes a fair amount
> > > of changes to VFS files (and also the VFS tree and docs tree are out of
> > > sync right now with the recent work by Mauro and Neil).
> >
> > Al, do you have any thoughts on how you want to handle this? I was about
> > to apply Jeff Layton's vfs.txt update, but would rather not create
> > conflicts unnecessarily. Let me know if you'd like me to pick this work
> > up.
>
> Frankly, I would rather see that file be eventually replaced by something
> saner, and I'm not talking about the format.

Are you able to extrapolate on this comment please? Is this something
someone new to the VFS (me) can do with a little nudge in the right
direction or is this something that needs thorough knowledge of the VFS?

> Re Jeff's patch...
>
> + d_prune: called prior to pruning (i.e. unhashing and killing) a hashed
> + dentry from the dcache.
>
> is flat-out misguiding. First of all, it *is* called for unhashed dentries,
> TYVM. Furthermore, "prior to" is far too vague.

This patch includes documentation for d_prune() very similar to Jeff's
patch (taken from a comment somewhere in filesystems code IIRC). I can
have a go at working all the comments below into better documentation if
that is useful (dependant on answer to question above).


thanks,
Tobin.

(leaving text below for reference)

> What really happens: there's a point in state diagram for dentries where
> we commit to destroying a dentry and start taking it apart. That transition
> happens with ->d_lock of dentry, ->i_lock of its inode (if any) and
> ->d_lock of the parent (again, if any) held; ->d_prune() is the last
> chance for filesystem to see the (now doomed) dentry still intact.
>
> It doesn't matter whether it's hashed or not, etc. The locks held
> are sufficient to stabilize pretty much everything[1] in dentry and
> nothing is destroyed yet. The only apparent exception is ->d_count,
> but that's not real - we are guaranteed that there had been no other
> counted references to dentry at the decision point and that none
> could've been added. So this "oh, it's not 0 now, it's gone negative
> after lockref_mark_dead() the caller has just done" is a red herring.
>
> ->d_prune() must not drop/regain any of the locks held by caller.
> It must _not_ free anything attached to dentry - that belongs
> later in the shutdown sequence. If anything, I'm tempted to
> make it take const struct dentry * as argument, just to make
> that clear.
>
> No new (counted) references can be acquired by that point;
> lockless dcache lookup might find our dentry a match, but
> result of such lookup is not going to be legitimized - it's
> doomed to be thrown out as stale.
>
> It really makes more sense as part of struct dentry lifecycle
> description...
>
> [1] in theory, ->d_time might be changed by overlapping lockless
> call of ->d_revalidate(). Up to filesystem - VFS doesn't touch
> that field (and AFAICS only NFS uses it these days).

2019-04-02 23:47:05

by Ian Kent

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Tue, 2019-04-02 at 20:08 +0100, Al Viro wrote:
> On Tue, Apr 02, 2019 at 06:54:01PM +0100, Al Viro wrote:
> > static void autofs_dentry_release(struct dentry *de)
> > {
> > struct autofs_info *ino = autofs_dentry_ino(de);
> > struct autofs_sb_info *sbi = autofs_sbi(de->d_sb);
> >
> > pr_debug("releasing %p\n", de);
> >
> > if (!ino)
> > return;
> > ...
> > autofs_free_ino(ino);
> > }
> > with autofs_free_ino() being straight kfree(). Which means
> > that the lockless case of autofs_d_manage() can run into
> > autofs_dentry_ino(dentry) getting freed right under it.
> >
> > And there we do have this reachable:
> > int autofs_expire_wait(const struct path *path, int rcu_walk)
> > {
> > struct dentry *dentry = path->dentry;
> > struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb);
> > struct autofs_info *ino = autofs_dentry_ino(dentry);
> > int status;
> > int state;
> >
> > /* Block on any pending expire */
> > if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
> > return 0;
> > if (rcu_walk)
> > return -ECHILD;
> >
> > the second check buggers off in lockless mode; the first one
> > can be done in lockless mode just fine, so AFAICS we do have
> > a problem there. Smells like we ought to make that kfree
> > in autofs_free_ino() RCU-delayed... Ian, have you, by any
> > chance, run into reports like that? Use-after-free or
> > oopsen in autofs_expire_wait() and friends, that is...

Never seen any reports of this but that doesn't mean it shouldn't
be fixed.

>
> Alternatively, we could clear ->d_fsdata in autofs_d_release()
> under ->d_lock and have all potentially lockless users of
> autofs_dentry_ino() take ->d_lock around messing with that.
> I'd still prefer to do it as below, though. Ian, do you have
> any objections against the following and, if you are OK with
> it, which tree would you prefer it to go through?

I can't think of any reason to add additional locking over
using an rcu free.

Please feel free to send this via your tree as your close
to what's being done and need to keep track of it.

>
> autofs: fix use-after-free in lockless ->d_manage()
>
> autofs_d_release() can overlap with lockless ->d_manage(),
> ending up with autofs_dentry_ino() freed under the latter.
> Make freeing autofs_info instances RCU-delayed...
>
> Signed-off-by: Al Viro <[email protected]>
> ---
> diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
> index 70c132acdab1..e1091312abe1 100644
> --- a/fs/autofs/autofs_i.h
> +++ b/fs/autofs/autofs_i.h
> @@ -71,6 +71,7 @@ struct autofs_info {
>
> kuid_t uid;
> kgid_t gid;
> + struct rcu_head rcu;
> };
>
> #define AUTOFS_INF_EXPIRING (1<<0) /* dentry in the process of expiring */
> diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
> index 80597b88718b..fb0225f21c12 100644
> --- a/fs/autofs/inode.c
> +++ b/fs/autofs/inode.c
> @@ -36,7 +36,7 @@ void autofs_clean_ino(struct autofs_info *ino)
>
> void autofs_free_ino(struct autofs_info *ino)
> {
> - kfree(ino);
> + kfree_rcu(ino, rcu);
> }
>
> void autofs_kill_sb(struct super_block *sb)

2019-04-02 23:59:15

by Ian Kent

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Tue, 2019-04-02 at 20:08 +0100, Al Viro wrote:
> On Tue, Apr 02, 2019 at 06:54:01PM +0100, Al Viro wrote:
> > static void autofs_dentry_release(struct dentry *de)
> > {
> > struct autofs_info *ino = autofs_dentry_ino(de);
> > struct autofs_sb_info *sbi = autofs_sbi(de->d_sb);
> >
> > pr_debug("releasing %p\n", de);
> >
> > if (!ino)
> > return;
> > ...
> > autofs_free_ino(ino);
> > }
> > with autofs_free_ino() being straight kfree(). Which means
> > that the lockless case of autofs_d_manage() can run into
> > autofs_dentry_ino(dentry) getting freed right under it.
> >
> > And there we do have this reachable:
> > int autofs_expire_wait(const struct path *path, int rcu_walk)
> > {
> > struct dentry *dentry = path->dentry;
> > struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb);
> > struct autofs_info *ino = autofs_dentry_ino(dentry);
> > int status;
> > int state;
> >
> > /* Block on any pending expire */
> > if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))

Oh yes, this is saying the dentry hasn't been selected
for expire on the first pass, there's a second pass at
expire selection so there's a delay there and both flags
(this one and the expiring flag) are kept throughout the
expire operation if dentry is selected.

That might be partly why an oops has never been seen but
path walks can occur at any time so it's a bit puzzling.

LOL, and Neil probably can't remember the deeper detail
on what he did there now either.

> > return 0;
> > if (rcu_walk)
> > return -ECHILD;
> >
> > the second check buggers off in lockless mode; the first one
> > can be done in lockless mode just fine, so AFAICS we do have
> > a problem there. Smells like we ought to make that kfree
> > in autofs_free_ino() RCU-delayed... Ian, have you, by any
> > chance, run into reports like that? Use-after-free or
> > oopsen in autofs_expire_wait() and friends, that is...
>
> Alternatively, we could clear ->d_fsdata in autofs_d_release()
> under ->d_lock and have all potentially lockless users of
> autofs_dentry_ino() take ->d_lock around messing with that.
> I'd still prefer to do it as below, though. Ian, do you have
> any objections against the following and, if you are OK with
> it, which tree would you prefer it to go through?
>
> autofs: fix use-after-free in lockless ->d_manage()
>
> autofs_d_release() can overlap with lockless ->d_manage(),
> ending up with autofs_dentry_ino() freed under the latter.
> Make freeing autofs_info instances RCU-delayed...
>
> Signed-off-by: Al Viro <[email protected]>
> ---
> diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
> index 70c132acdab1..e1091312abe1 100644
> --- a/fs/autofs/autofs_i.h
> +++ b/fs/autofs/autofs_i.h
> @@ -71,6 +71,7 @@ struct autofs_info {
>
> kuid_t uid;
> kgid_t gid;
> + struct rcu_head rcu;
> };
>
> #define AUTOFS_INF_EXPIRING (1<<0) /* dentry in the process of expiring */
> diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
> index 80597b88718b..fb0225f21c12 100644
> --- a/fs/autofs/inode.c
> +++ b/fs/autofs/inode.c
> @@ -36,7 +36,7 @@ void autofs_clean_ino(struct autofs_info *ino)
>
> void autofs_free_ino(struct autofs_info *ino)
> {
> - kfree(ino);
> + kfree_rcu(ino, rcu);
> }
>
> void autofs_kill_sb(struct super_block *sb)

2019-04-03 00:56:12

by NeilBrown

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Wed, Apr 03 2019, Ian Kent wrote:

> On Tue, 2019-04-02 at 20:08 +0100, Al Viro wrote:
>> On Tue, Apr 02, 2019 at 06:54:01PM +0100, Al Viro wrote:
>> > static void autofs_dentry_release(struct dentry *de)
>> > {
>> > struct autofs_info *ino = autofs_dentry_ino(de);
>> > struct autofs_sb_info *sbi = autofs_sbi(de->d_sb);
>> >
>> > pr_debug("releasing %p\n", de);
>> >
>> > if (!ino)
>> > return;
>> > ...
>> > autofs_free_ino(ino);
>> > }
>> > with autofs_free_ino() being straight kfree(). Which means
>> > that the lockless case of autofs_d_manage() can run into
>> > autofs_dentry_ino(dentry) getting freed right under it.
>> >
>> > And there we do have this reachable:
>> > int autofs_expire_wait(const struct path *path, int rcu_walk)
>> > {
>> > struct dentry *dentry = path->dentry;
>> > struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb);
>> > struct autofs_info *ino = autofs_dentry_ino(dentry);
>> > int status;
>> > int state;
>> >
>> > /* Block on any pending expire */
>> > if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
>
> Oh yes, this is saying the dentry hasn't been selected
> for expire on the first pass, there's a second pass at
> expire selection so there's a delay there and both flags
> (this one and the expiring flag) are kept throughout the
> expire operation if dentry is selected.
>
> That might be partly why an oops has never been seen but
> path walks can occur at any time so it's a bit puzzling.
>
> LOL, and Neil probably can't remember the deeper detail
> on what he did there now either.

It seems very likely that this was just a subtlety that I missed.
I doesn't help that "ino" isn't actually and inode and isn't freed like
an inode, but that is no excuse.

When we add the rcu_head linkage to 'struct autofs_info', we might as
well remove the 'struct inode' from there - it doesn't seem to have been
used for years.

Thanks,
NeilBrown


Attachments:
signature.asc (847.00 B)

2019-04-03 01:01:58

by NeilBrown

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Tue, Apr 02 2019, Al Viro wrote:

> On Tue, Apr 02, 2019 at 09:49:34AM -0600, Jonathan Corbet wrote:
>> On Wed, 27 Mar 2019 16:16:53 +1100
>> "Tobin C. Harding" <[email protected]> wrote:
>>
>> > Hi Al,
>> >
>> > This series converts the VFS file Documentation/filesystems/vfs.txt to
>> > reStructuredText format. Please consider taking this series through
>> > your tree as apposed to Jon's tree because this set makes a fair amount
>> > of changes to VFS files (and also the VFS tree and docs tree are out of
>> > sync right now with the recent work by Mauro and Neil).
>>
>> Al, do you have any thoughts on how you want to handle this? I was about
>> to apply Jeff Layton's vfs.txt update, but would rather not create
>> conflicts unnecessarily. Let me know if you'd like me to pick this work
>> up.
>
> Frankly, I would rather see that file be eventually replaced by something
> saner, and I'm not talking about the format. Re Jeff's patch...
>
> + d_prune: called prior to pruning (i.e. unhashing and killing) a hashed
> + dentry from the dcache.
>
> is flat-out misguiding. First of all, it *is* called for unhashed dentries,
> TYVM. Furthermore, "prior to" is far too vague.
>
> What really happens: there's a point in state diagram for dentries where
> we commit to destroying a dentry and start taking it apart. That transition
> happens with ->d_lock of dentry, ->i_lock of its inode (if any) and
> ->d_lock of the parent (again, if any) held; ->d_prune() is the last
> chance for filesystem to see the (now doomed) dentry still intact.
>
> It doesn't matter whether it's hashed or not, etc. The locks held
> are sufficient to stabilize pretty much everything[1] in dentry and
> nothing is destroyed yet. The only apparent exception is ->d_count,
> but that's not real - we are guaranteed that there had been no other
> counted references to dentry at the decision point and that none
> could've been added. So this "oh, it's not 0 now, it's gone negative
> after lockref_mark_dead() the caller has just done" is a red herring.
>
> ->d_prune() must not drop/regain any of the locks held by caller.
> It must _not_ free anything attached to dentry - that belongs
> later in the shutdown sequence. If anything, I'm tempted to
> make it take const struct dentry * as argument, just to make
> that clear.
>
> No new (counted) references can be acquired by that point;
> lockless dcache lookup might find our dentry a match, but
> result of such lookup is not going to be legitimized - it's
> doomed to be thrown out as stale.
>
> It really makes more sense as part of struct dentry lifecycle
> description...

I would find it useful if the documentation said something about why
this API exists at all. As you say, it cannot change the dentry - so
what is it expected to do.

I had a look at the two in-tree users and my guess is that it can be
useful if the filesystem caches some other information which would be
invalidated by a dentry being removed.
I *think* cephfs has a flag which records if "All entries in a directory
are currently in the dcache". When a dentry is pruned, that flag needs
to be cleared.

i.e. ->d_prune allows a filesystem to maintain summary state about what
is currently in the dcache.
??

Thanks,
NeilBrown

>
> [1] in theory, ->d_time might be changed by overlapping lockless
> call of ->d_revalidate(). Up to filesystem - VFS doesn't touch
> that field (and AFAICS only NFS uses it these days).


Attachments:
signature.asc (847.00 B)

2019-04-03 01:45:16

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Wed, Apr 03, 2019 at 12:00:54PM +1100, NeilBrown wrote:

> I would find it useful if the documentation said something about why
> this API exists at all. As you say, it cannot change the dentry - so
> what is it expected to do.

*shrug*

It tell filesystem that this dentry is going away now.

> I had a look at the two in-tree users and my guess is that it can be
> useful if the filesystem caches some other information which would be
> invalidated by a dentry being removed.
> I *think* cephfs has a flag which records if "All entries in a directory
> are currently in the dcache". When a dentry is pruned, that flag needs
> to be cleared.
>
> i.e. ->d_prune allows a filesystem to maintain summary state about what
> is currently in the dcache.

For one thing... Or, if you keep a (non-counting) reference to that
dentry, this tells you to forget it, etc.

I can think of other uses; it's really just telling the fs that this
is becoming an ex-parrot.

2019-04-03 19:36:29

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Wed, Apr 03, 2019 at 11:55:01AM +1100, NeilBrown wrote:

> It seems very likely that this was just a subtlety that I missed.
> I doesn't help that "ino" isn't actually and inode and isn't freed like
> an inode, but that is no excuse.
>
> When we add the rcu_head linkage to 'struct autofs_info', we might as
> well remove the 'struct inode' from there - it doesn't seem to have been
> used for years.

Umm... I can do that, but then we get greater potential for conflicts
and the whole thing might be better off in autofs tree. Ian, up to you -
I can throw both into a never-rebased branch, so you could merge it
into your tree; the first one is -stable fodder, though...

2019-04-03 19:48:30

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Wed, Apr 03, 2019 at 06:25:20AM +1100, Tobin C. Harding wrote:
> On Tue, Apr 02, 2019 at 05:48:24PM +0100, Al Viro wrote:
> > On Tue, Apr 02, 2019 at 09:49:34AM -0600, Jonathan Corbet wrote:
> > > On Wed, 27 Mar 2019 16:16:53 +1100
> > > "Tobin C. Harding" <[email protected]> wrote:
> > >
> > > > Hi Al,
> > > >
> > > > This series converts the VFS file Documentation/filesystems/vfs.txt to
> > > > reStructuredText format. Please consider taking this series through
> > > > your tree as apposed to Jon's tree because this set makes a fair amount
> > > > of changes to VFS files (and also the VFS tree and docs tree are out of
> > > > sync right now with the recent work by Mauro and Neil).
> > >
> > > Al, do you have any thoughts on how you want to handle this? I was about
> > > to apply Jeff Layton's vfs.txt update, but would rather not create
> > > conflicts unnecessarily. Let me know if you'd like me to pick this work
> > > up.
> >
> > Frankly, I would rather see that file be eventually replaced by something
> > saner, and I'm not talking about the format.
>
> Are you able to extrapolate on this comment please? Is this something
> someone new to the VFS (me) can do with a little nudge in the right
> direction or is this something that needs thorough knowledge of the VFS?

Put it that way - IMO the best way to do it is not a list of methods with
explanations what each does, but a bunch of per-data structure documents
describing their life cycles. The fundamental ones for VFS would be
* inode
* dentry
* super_block
* (vfs)mount
* file
* files_struct
Having a list of methods is nice, but those would be better off with short
description along with "see <document> for details, including the locking,
etc."; said short descriptions make little sense without the background...

2019-04-03 21:01:23

by Tobin C. Harding

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Wed, Apr 03, 2019 at 08:47:21PM +0100, Al Viro wrote:
> On Wed, Apr 03, 2019 at 06:25:20AM +1100, Tobin C. Harding wrote:
> > On Tue, Apr 02, 2019 at 05:48:24PM +0100, Al Viro wrote:
> > > On Tue, Apr 02, 2019 at 09:49:34AM -0600, Jonathan Corbet wrote:
> > > > On Wed, 27 Mar 2019 16:16:53 +1100
> > > > "Tobin C. Harding" <[email protected]> wrote:
> > > >
> > > > > Hi Al,
> > > > >
> > > > > This series converts the VFS file Documentation/filesystems/vfs.txt to
> > > > > reStructuredText format. Please consider taking this series through
> > > > > your tree as apposed to Jon's tree because this set makes a fair amount
> > > > > of changes to VFS files (and also the VFS tree and docs tree are out of
> > > > > sync right now with the recent work by Mauro and Neil).
> > > >
> > > > Al, do you have any thoughts on how you want to handle this? I was about
> > > > to apply Jeff Layton's vfs.txt update, but would rather not create
> > > > conflicts unnecessarily. Let me know if you'd like me to pick this work
> > > > up.
> > >
> > > Frankly, I would rather see that file be eventually replaced by something
> > > saner, and I'm not talking about the format.
> >
> > Are you able to extrapolate on this comment please? Is this something
> > someone new to the VFS (me) can do with a little nudge in the right
> > direction or is this something that needs thorough knowledge of the VFS?
>
> Put it that way - IMO the best way to do it is not a list of methods with
> explanations what each does, but a bunch of per-data structure documents
> describing their life cycles. The fundamental ones for VFS would be
> * inode
> * dentry
> * super_block
> * (vfs)mount
> * file
> * files_struct
> Having a list of methods is nice, but those would be better off with short
> description along with "see <document> for details, including the locking,
> etc."; said short descriptions make little sense without the background...

Ok, got it. Thanks.

Tobin

2019-04-03 23:29:47

by Ian Kent

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Wed, 2019-04-03 at 11:55 +1100, NeilBrown wrote:
> On Wed, Apr 03 2019, Ian Kent wrote:
>
> > On Tue, 2019-04-02 at 20:08 +0100, Al Viro wrote:
> > > On Tue, Apr 02, 2019 at 06:54:01PM +0100, Al Viro wrote:
> > > > static void autofs_dentry_release(struct dentry *de)
> > > > {
> > > > struct autofs_info *ino = autofs_dentry_ino(de);
> > > > struct autofs_sb_info *sbi = autofs_sbi(de->d_sb);
> > > >
> > > > pr_debug("releasing %p\n", de);
> > > >
> > > > if (!ino)
> > > > return;
> > > > ...
> > > > autofs_free_ino(ino);
> > > > }
> > > > with autofs_free_ino() being straight kfree(). Which means
> > > > that the lockless case of autofs_d_manage() can run into
> > > > autofs_dentry_ino(dentry) getting freed right under it.
> > > >
> > > > And there we do have this reachable:
> > > > int autofs_expire_wait(const struct path *path, int rcu_walk)
> > > > {
> > > > struct dentry *dentry = path->dentry;
> > > > struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb);
> > > > struct autofs_info *ino = autofs_dentry_ino(dentry);
> > > > int status;
> > > > int state;
> > > >
> > > > /* Block on any pending expire */
> > > > if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
> >
> > Oh yes, this is saying the dentry hasn't been selected
> > for expire on the first pass, there's a second pass at
> > expire selection so there's a delay there and both flags
> > (this one and the expiring flag) are kept throughout the
> > expire operation if dentry is selected.
> >
> > That might be partly why an oops has never been seen but
> > path walks can occur at any time so it's a bit puzzling.
> >
> > LOL, and Neil probably can't remember the deeper detail
> > on what he did there now either.
>
> It seems very likely that this was just a subtlety that I missed.
> I doesn't help that "ino" isn't actually and inode and isn't freed like
> an inode, but that is no excuse.

I've become accustom to the naming so that doesn't occur to
me, ;)

>
> When we add the rcu_head linkage to 'struct autofs_info', we might as
> well remove the 'struct inode' from there - it doesn't seem to have been
> used for years.

That's a good point, I've thought about doing so several
times but haven't got around to it.

Ian

2019-04-04 06:31:12

by Ian Kent

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] Convert vfs.txt to vfs.rst

On Wed, 2019-04-03 at 20:35 +0100, Al Viro wrote:
> On Wed, Apr 03, 2019 at 11:55:01AM +1100, NeilBrown wrote:
>
> > It seems very likely that this was just a subtlety that I missed.
> > I doesn't help that "ino" isn't actually and inode and isn't freed like
> > an inode, but that is no excuse.
> >
> > When we add the rcu_head linkage to 'struct autofs_info', we might as
> > well remove the 'struct inode' from there - it doesn't seem to have been
> > used for years.
>
> Umm... I can do that, but then we get greater potential for conflicts
> and the whole thing might be better off in autofs tree. Ian, up to you -
> I can throw both into a never-rebased branch, so you could merge it
> into your tree; the first one is -stable fodder, though...

Ha, as unlikely as that usually is, given the low churn in the autofs
code, conflicts might be a problem.

I'm likely to change the autofs info flags field to unsigned as part
of implementing a suggestion from Neil (quite some time ago now) to
fix the AT_NO_AUTOMOUNT handling.

So I'll hold onto the patch to remove the inode field, include it as
part of that change, and forward it as low priority via Andrew.

I'll send your rcu free patch back to you (with an added comment in
the description) as a higher priority change.

Ian