--- /dev/null
+=========================================================
+¤³¤ì¤Ï¡¢
+Linux-3.6/Documentation/filesystems/Locking ¤ÎÏÂÌõ¤Ç¤¹¡£
+ËÝÌõÃÄÂΡ§ JF ¥×¥í¥¸¥§¥¯¥È < http://linuxjf.sourceforge.jp/ >
+¹¹¿·Æü ¡§ 2012/10/02
+ËÝÌõ¼Ô ¡§ Seiji Kaneko < skaneko at mbn dot or dot jp >
+ººÆÉ¼Ô ¡§ Takeshi Hamasaki < hmatrjp at users dot sourceforge dot jp >
+=========================================================
+# The text below describes the locking rules for VFS-related methods.
+#It is (believed to be) up-to-date. *Please*, if you change anything in
+#prototypes or locking protocols - update this file. And update the relevant
+#instances in the tree, don't leave that to maintainers of filesystems/devices/
+#etc. At the very least, put the list of dubious cases in the end of this file.
+#Don't turn it into log - maintainers of out-of-the-tree code are supposed to
+#be able to use diff(1).
+# Thing currently missing here: socket operations. Alexey?
+°Ê²¼¤Îʸ½ñ¤Ï VFS ´ØÏ¢¥á¥½¥Ã¥É¤Ç¤Î¥í¥Ã¥¯¼èÆÀµ¬Â§¤òµºÜ¤·¤¿¤â¤Î¤Ç¤¹¡£¤³¤ì¤Ï
+ºÇ¿·ÈÇ (¤Î¤Ï¤º) ¤Ç¤¹¡£¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥È¥¿¥¤¥×¤ä¥í¥Ã¥¯¥×¥í¥È¥³¥ë¤Ë²¿¤é¤«¤Î
+Êѹ¹¤ò²Ã¤¨¤¿¾ì¹ç¤Ë¤Ï¡¢¡öɬ¤º¡ö ¤³¤Î¥Õ¥¡¥¤¥ë¤ò¹¹¿·¤·¤Æ¤¯¤À¤µ¤¤¡£¤Þ¤¿¡¢¥Ä¥ê¡¼
+Æâ¤Î´ØÏ¢¥¤¥ó¥¹¥¿¥ó¥¹¤ò¡¢Â¾¤Î¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤ä¥Ç¥Ð¥¤¥¹¤Ê¤É¤Î¥á¥ó¥Æ¥Ê¤ËǤ¤»¤º¡¢
+¼«Ê¬¤Ç¹¹¿·¤·¤Æ¤¯¤À¤µ¤¤¡£¾¯¤Ê¤¯¤È¤â¡¢Ì¤½¤Àµ¤ÎÆâÍƤϤ³¤Î¥Õ¥¡¥¤¥ë¤ÎËöÈø¤Î¥ê¥¹
+¥È¤Ë²Ã¤¨¤Æ¤¯¤À¤µ¤¤¡£¤³¤ÎÆâÍƤò¥í¥°¤Ë¤Ï¤·¤Ê¤¤¤Ç¤¯¤À¤µ¤¤¡£¥Ä¥ê¡¼³°¤Î¥³¡¼¥É¤Î
+¥á¥ó¥Æ¥Ê¤Ï diff(1) ¤ò»È¤¦¤³¤È¤¬¤Ç¤¤ë¤È¤¤¤¦ÁÛÄê¤Ç¤¹¤Î¤Ç¡£
+¸½ºßÉÔ¤·¤Æ¤¤¤ë¤Î¤Ï¡¢¥½¥±¥Ã¥È½èÍý¤Ç¤¹¡£Alexey ¤µ¤ó¡¢¤¤¤«¤¬¡£
+
+--------------------------- dentry_operations --------------------------
+prototypes:
+ int (*d_revalidate)(struct dentry *, unsigned int);
+ int (*d_hash)(const struct dentry *, const struct inode *,
+ struct qstr *);
+ int (*d_compare)(const struct dentry *, const struct inode *,
+ const struct dentry *, const struct inode *,
+ unsigned int, const char *, const struct qstr *);
+ int (*d_delete)(struct dentry *);
+ void (*d_release)(struct dentry *);
+ void (*d_iput)(struct dentry *, struct inode *);
+ char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
+ struct vfsmount *(*d_automount)(struct path *path);
+ int (*d_manage)(struct dentry *, bool);
+
+#locking rules:
+# rename_lock ->d_lock may block rcu-walk
+#d_revalidate: no no yes (ref-walk) maybe
+#d_hash no no no maybe
+#d_compare: yes no no maybe
+#d_delete: no yes no no
+#d_release: no no yes no
+#d_prune: no yes no no
+#d_iput: no no yes no
+#d_dname: no no no no
+#d_automount: no no yes no
+#d_manage: no no yes (ref-walk) maybe
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë
+ rename_lock ->d_lock ¥Ö¥í¥Ã¥¯²ÄǽÀ rcu-walk
+d_revalidate: ¤¤¤¤¤¨ ¤¤¤¤¤¨ ¤Ï¤¤ (ref-walk) ²ÄǽÀÍ
+d_hash ¤¤¤¤¤¨ ¤¤¤¤¤¨ ¤¤¤¤¤¨ ²ÄǽÀÍ
+d_compare: ¤Ï¤¤ ¤¤¤¤¤¨ ¤¤¤¤¤¨ ²ÄǽÀÍ
+d_delete: ¤¤¤¤¤¨ ¤Ï¤¤ ¤¤¤¤¤¨ ¤¤¤¤¤¨
+d_release: ¤¤¤¤¤¨ ¤¤¤¤¤¨ ¤Ï¤¤ ¤¤¤¤¤¨
+d_prune: ¤¤¤¤¤¨ ¤Ï¤¤ ¤¤¤¤¤¨ ¤¤¤¤¤¨
+d_iput: ¤¤¤¤¤¨ ¤¤¤¤¤¨ ¤Ï¤¤ ¤¤¤¤¤¨
+d_dname: ¤¤¤¤¤¨ ¤¤¤¤¤¨ ¤¤¤¤¤¨ ¤¤¤¤¤¨
+d_automount: ¤¤¤¤¤¨ ¤¤¤¤¤¨ ¤Ï¤¤ ¤¤¤¤¤¨
+d_manage: ¤¤¤¤¤¨ ¤¤¤¤¤¨ ¤Ï¤¤ (ref-walk) ²ÄǽÀÍ
+
+--------------------------- inode_operations ---------------------------
+prototypes:
+ int (*create) (struct inode *,struct dentry *,umode_t, bool);
+ struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
+ 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 *);
+ int (*readlink) (struct dentry *, char __user *,int);
+ void * (*follow_link) (struct dentry *, struct nameidata *);
+ void (*put_link) (struct dentry *, struct nameidata *, void *);
+ void (*truncate) (struct inode *);
+ int (*permission) (struct inode *, int, unsigned int);
+ int (*get_acl)(struct inode *, int);
+ int (*setattr) (struct dentry *, struct iattr *);
+ int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
+ int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+ ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
+ ssize_t (*listxattr) (struct dentry *, char *, size_t);
+ int (*removexattr) (struct dentry *, const char *);
+ int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
+ void (*update_time)(struct inode *, struct timespec *, int);
+ int (*atomic_open)(struct inode *, struct dentry *,
+ struct file *, unsigned open_flag,
+ umode_t create_mode, int *opened);
+
+#locking rules:
+# all may block
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë
+ ¤¹¤Ù¤Æ¥Ö¥í¥Ã¥¯²ÄǽÀ¤¢¤ê¡£
+ i_mutex(inode)
+#lookup: yes
+#create: yes
+#link: yes (both)
+#mknod: yes
+#symlink: yes
+#mkdir: yes
+#unlink: yes (both)
+#rmdir: yes (both) (see below)
+#rename: yes (all) (see below)
+#readlink: no
+#follow_link: no
+#put_link: no
+#truncate: yes (see below)
+#setattr: yes
+#permission: no (may not block if called in rcu-walk mode)
+#get_acl: no
+#getattr: no
+#setxattr: yes
+#getxattr: no
+#listxattr: no
+#removexattr: yes
+#fiemap: no
+#update_time: no
+#atomic_open: yes
+lookup: ¤Ï¤¤
+create: ¤Ï¤¤
+link: ¤Ï¤¤ (ξÊý¤Ç)
+mknod: ¤Ï¤¤
+symlink: ¤Ï¤¤
+mkdir: ¤Ï¤¤
+unlink: ¤Ï¤¤ (ξÊý¤Ç)
+rmdir: ¤Ï¤¤ (ξÊý¤Ç) (²¼µ»²¾È)
+rename: ¤Ï¤¤ (¤¹¤Ù¤Æ) (²¼µ»²¾È)
+readlink: ¤¤¤¤¤¨
+follow_link: ¤¤¤¤¤¨
+put_link: ¤¤¤¤¤¨
+truncate: ¤Ï¤¤ (²¼µ»²¾È)
+setattr: ¤Ï¤¤
+permission: ¤¤¤¤¤¨ (rcu-walk ¥â¡¼¥É¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¡¢¥Ö¥í¥Ã¥¯ÉÔ²Ä)
+get_acl: ¤¤¤¤¤¨
+getattr: ¤¤¤¤¤¨
+setxattr: ¤Ï¤¤
+getxattr: ¤¤¤¤¤¨
+listxattr: ¤¤¤¤¤¨
+removexattr: ¤Ï¤¤
+fiemap: ¤¤¤¤¤¨
+update_time: ¤¤¤¤¤¨
+atomic_open: ¤Ï¤¤
+
+# Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
+#victim.
+# cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
+# ->truncate() is never called directly - it's a callback, not a
+#method. It's called by vmtruncate() - deprecated library function normally used by
+#->setattr(). Locking information above applies to that call (i.e. is
+#inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had been
+#passed).
+#
+#See Documentation/filesystems/directory-locking for more detailed discussion
+#of the locking scheme for directory operations.
+ ²Ã¤¨¤Æ¡¢->rmdir(), ->unlink() ¤ª¤è¤Ó ->rename() ¤ÏÁàºî¤µ¤ì¤ë¦¤Î ->i_mutex
+ ¤ò»ý¤Á¤Þ¤¹¡£
+ ¥Ç¥£¥ì¥¯¥È¥ê¤òÅϤë ->rename() ¤Ï¡¢¥¹¡¼¥Ñ¡¼¥Ö¥í¥Ã¥¯¤´¤È¤Î
+ ->s_vfs_rename_sem ¤ò»ý¤Á¤Þ¤¹¡£->truncate() ¤ÏľÀܤϸƤФì¤Þ¤»¤ó¡£
+ ¤³¤ì¤Ï¥³¡¼¥ë¥Ð¥Ã¥¯¤Ç¡¢¥á¥½¥Ã¥É¤Ç¤Ï¤Ê¤¤¤¿¤á¤Ç¤¹¡£¤³¤ì¤Ï vmtruncate()
+ - Ä̾ï¤Ï ->setattr() ¤«¤é»È¤ï¤ì¤ëÈó¿ä¾©¤È¤Ê¤Ã¤¿¥é¥¤¥Ö¥é¥ê´Ø¿ô - ¤«¤é¸Æ¤Ð¤ì¤Þ
+ ¤¹¡£¾åµ¤Î¥í¥Ã¥¯¾ðÊó¤Ï¤³¤Î¸Æ¤Ó½Ð¤·¤Ë¤âŬÍѤµ¤ì¤Þ¤¹ (¤Ä¤Þ¤ê¡¢
+ ->setattr() ¤«¤é·Ñ¾µ¤µ¤ì¤Þ¤¹¡£vmtruncate() ¤Ï ATTR_SIZE ¤¬ÅϤµ¤ì¤¿
+ ¾ì¹ç¤Ë»È¤ï¤ì¤Þ¤¹)¡£
+
+¥Ç¥£¥ì¥¯¥È¥êÁàºî¤Ç¤Î¥í¥Ã¥¯ÊýË¡¤Ë¤Ä¤¤¤Æ¤Î¾ÜºÙ¤Ï¡¢
+Documentation/filesystems/directory-locking ¤ò»²¾È¤¯¤À¤µ¤¤¡£
+--------------------------- super_operations ---------------------------
+prototypes:
+ 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 *);
+ int (*sync_fs)(struct super_block *sb, int wait);
+ void (*write_super_lockfs) (struct super_block *);
+ void (*unlockfs) (struct super_block *);
+ int (*statfs) (struct dentry *, struct kstatfs *);
+ int (*remount_fs) (struct super_block *, int *, char *);
+ void (*umount_begin) (struct super_block *);
+ int (*show_options)(struct seq_file *, struct dentry *);
+ 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);
+ int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
+
+#locking rules:
+# All may block [not true, see below]
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë
+ ¤¹¤Ù¤Æ¥Ö¥í¥Ã¥¯¤Î²ÄǽÀ¤¢¤ê (¤Û¤ó¤È¤¦¤Ï°Û¤Ê¤ë¡£°Ê²¼»²¾È)¡£
+# s_umount
+#alloc_inode:
+#destroy_inode:
+#dirty_inode:
+#write_inode:
+#drop_inode: !!!inode->i_lock!!!
+#evict_inode:
+#put_super: write
+#sync_fs: read
+#freeze_fs: write
+#unfreeze_fs: write
+#statfs: maybe(read) (see below)
+#remount_fs: write
+#umount_begin: no
+#show_options: no (namespace_sem)
+#quota_read: no (see below)
+#quota_write: no (see below)
+#bdev_try_to_free_page: no (see below)
+ s_umount
+alloc_inode:
+destroy_inode:
+dirty_inode:
+write_inode:
+drop_inode: !!!inode->i_lock!!!
+evict_inode:
+put_super: ½ñ¤¹þ¤ß
+sync_fs: Æɤ߽Ф·
+freeze_fs: ½ñ¤¹þ¤ß
+unfreeze_fs: ½ñ¤¹þ¤ß
+statfs: ²ÄǽÀ¤¢¤ê(Æɤ߽Ф·) (²¼µ»²¾È)
+remount_fs: ½ñ¤¹þ¤ß
+umount_begin: ¤¤¤¤¤¨
+show_options: ¤¤¤¤¤¨ (namespace_sem)
+quota_read: ¤¤¤¤¤¨ (²¼µ»²¾È)
+quota_write: ¤¤¤¤¤¨ (²¼µ»²¾È)
+bdev_try_to_free_page: ¤¤¤¤¤¨ (²¼µ»²¾È)
+
+
+#->statfs() has s_umount (shared) when called by ustat(2) (native or
+#compat), but that's an accident of bad API; s_umount is used to pin
+#the superblock down when we only have dev_t given us by userland to
+#identify the superblock. Everything else (statfs(), fstatfs(), etc.)
+#doesn't hold it when calling ->statfs() - superblock is pinned down
+#by resolving the pathname passed to syscall.
+#->quota_read() and ->quota_write() functions are both guaranteed to
+#be the only ones operating on the quota file by the quota code (via
+#dqio_sem) (unless an admin really wants to screw up something and
+#writes to quota files with quotas on). For other details about locking
+#see also dquot_operations section.
+#->bdev_try_to_free_page is called from the ->releasepage handler of
+#the block device inode. See there for more details.
+->statfs() ¤Ï¡¢ustat(2) (¥Í¥¤¥Æ¥£¥Ö¤Þ¤¿¤Ï¸ß´¹¤ÎξÊý¶¦) ¤«¤é¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¡¢
+s_umount (¶¦Í) ¥í¥Ã¥¯¤ò¼èÆÀ¤·¤Þ¤¹¤¬¡¢¤³¤ì¤Ï¤Þ¤º¤¤ API ¤Î»ö¸Î¤È¤â¤¤¤¦¤Ù¤¤â
+¤Î¤Ç¤¹¡£¤³¤³¤Ç¡¢s_umount ¤Ï¡¢¥æ¡¼¥¶¥é¥ó¥É¤«¤é¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¥¹¡¼¥Ñ¥Ö¥í¥Ã¥¯¤ò
+ÆÃÄꤹ¤ë¤¿¤á¤Î¾ðÊó¤¬ dev_t ¤·¤«¤Ê¤¤¾ì¹ç¤Ë¡¢¥¹¡¼¥Ñ¥Ö¥í¥Ã¥¯¤ò¥Ô¥ó»ß¤á¤¹¤ë½èÍý
+¤ËÍѤ¤¤é¤ì¤Þ¤¹¡£Â¾¤ÎÁ´¤Æ¤Î¾ì¹ç (statfs(), fstatfs() ¤Ê¤É) ¤Ç¤Ï¡¢statfs() ¤ò
+¸Æ¤ÖºÝ¤Ë¤Ï s_umount ¤òÊÝ»ý¤·¤Þ¤»¤ó¡£¤³¤Á¤é¤Î¾ì¹ç¤Ë¤Ï¡¢syscall ¤«¤éÅϤµ¤ì¤¿
+¥Ñ¥¹Ì¾¤ò²ò·è¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¥¹¡¼¥Ñ¥Ö¥í¥Ã¥¯¤¬¥Ô¥ó»ß¤á¤µ¤ì¤Þ¤¹¡£
+->quota_read() ¤È ->quota_write() ¤ÎξÊý¤È¤â¡¢quota ¥Õ¥¡¥¤¥ë¤ò°·¤¦½èÍý¤Ï¤³
+¤ì¤À¤±¤Ç¤¢¤ë¤³¤È¤¬ quota ¥³¡¼¥É¤Ë¤è¤Ã¤ÆÊݾڤµ¤ì¤Æ¤¤¤Þ¤¹ (´ÉÍý¼Ô¤¬²¿¤«¤ò²õ¤·
+¤¿¤¯¤Æ¡¢quota ͸ú»þ¤Ë quota ¥Õ¥¡¥¤¥ë¤ËÂФ·¤Æ½ñ¤¹þ¤ß¤ò¹Ô¤ª¤¦¤È¤·¤Ê¤¤¸Â¤ê)¡£
+¥í¥Ã¥¯¤Ë´Ø¤¹¤ë¤³¤ì°Ê³°¤Î¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï¡¢dquot_operations ¥»¥¯¥·¥ç¥ó¤ò»²¾È
+¤¯¤À¤µ¤¤¡£
+->bdev_try_to_free_page ¤Ï¡¢¥Ö¥í¥Ã¥¯¥Ç¥Ð¥¤¥¹ inode ¤Î ->releasepage ¥Ï¥ó¥É
+¥é¤«¤é¸Æ¤Ð¤ì¤Þ¤¹¡£¾ÜºÙ¤Ï¤½¤Á¤é¤Î¦¤ò»²¾È¤¯¤À¤µ¤¤¡£
+
+--------------------------- file_system_type ---------------------------
+prototypes:
+ int (*get_sb) (struct file_system_type *, int,
+ const char *, void *, struct vfsmount *);
+ struct dentry *(*mount) (struct file_system_type *, int,
+ const char *, void *);
+ void (*kill_sb) (struct super_block *);
+#locking rules:
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë
+# may block
+#get_sb yes
+#mount yes
+#kill_sb yes
+ ¥Ö¥í¥Ã¥¯¤Î²ÄǽÀ
+get_sb ¤¢¤ê
+mount ¤¢¤ê
+kill_sb ¤¢¤ê
+
+#->mount() returns ERR_PTR or the root dentry; its superblock should be locked
+#on return.
+#->kill_sb() takes a write-locked superblock, does all shutdown work on it,
+#unlocks and drops the reference.
+->mount() ¤Ï¡¢ERR_PTR ¤Þ¤¿¤Ï root dentry ¤òÊÖ¤·¤Þ¤¹¡£¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Î
+¥¹¡¼¥Ñ¥Ö¥í¥Ã¥¯¤ÏÌá¤ê»þ¤Ë¥í¥Ã¥¯¤·¤Æ¤ª¤¯¤Ù¤¤Ç¤¹¡£
+->kill_sb() ¤Ï½ñ¤¹þ¤ß¥í¥Ã¥¯¤µ¤ì¤¿¥¹¡¼¥Ñ¡¼¥Ö¥í¥Ã¥¯¤ò¼è¤ê¡¢¤½¤ì¤ËÂФ·¤ÆÁ´¤Æ
+¤Î¥·¥ã¥Ã¥È¥À¥¦¥ó½èÍý¤ò¹Ô¤¤¡¢¥í¥Ã¥¯¤ò²ò½ü¤·¤Æ»²¾È¤ò²òÊü¤·¤Þ¤¹¡£
+
+--------------------------- address_space_operations --------------------------
+prototypes:
+ int (*writepage)(struct page *page, struct writeback_control *wbc);
+ int (*readpage)(struct file *, struct page *);
+ int (*sync_page)(struct page *);
+ int (*writepages)(struct address_space *, struct writeback_control *);
+ int (*set_page_dirty)(struct page *page);
+ int (*readpages)(struct file *filp, struct address_space *mapping,
+ 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);
+ int (*write_end)(struct file *, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata);
+ sector_t (*bmap)(struct address_space *, sector_t);
+ int (*invalidatepage) (struct page *, unsigned long);
+ int (*releasepage) (struct page *, int);
+ void (*freepage)(struct page *);
+ int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs);
+ int (*get_xip_mem)(struct address_space *, pgoff_t, int, void **,
+ unsigned long *);
+ int (*migratepage)(struct address_space *, struct page *, struct page *);
+ int (*launder_page)(struct page *);
+ int (*is_partially_uptodate)(struct page *, read_descriptor_t *, unsigned long);
+ int (*error_remove_page)(struct address_space *, struct page *);
+ int (*swap_activate)(struct file *);
+ int (*swap_deactivate)(struct file *);
+
+#locking rules:
+# All except set_page_dirty and freepage may block
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë:
+ set_page_dirty ¤È freepage °Ê³°¤Ï¥Ö¥í¥Ã¥¯¤Î²ÄǽÀ¤¬¤¢¤ê¤Þ¤¹¡£
+
+# PageLocked(page) i_mutex
+#writepage: yes, unlocks (see below)
+#readpage: yes, unlocks
+#sync_page: maybe
+#writepages:
+#set_page_dirty no
+#readpages:
+#write_begin: locks the page yes
+#write_end: yes, unlocks yes
+#bmap:
+#invalidatepage: yes
+#releasepage: yes
+#freepage: yes
+#direct_IO:
+#get_xip_mem: maybe
+#migratepage: yes (both)
+#launder_page: yes
+#is_partially_uptodate: yes
+#error_remove_page: yes
+#swap_activate: no
+#swap_deactivate: no
+ PageLocked(page) i_mutex
+writepage: ¤Ï¤¤¡£¥¢¥ó¥í¥Ã¥¯¤·¤Þ¤¹ (²¼µ»²¾È)
+readpage: ¤Ï¤¤¡£¥¢¥ó¥í¥Ã¥¯¤·¤Þ¤¹
+sync_page: ²ÄǽÀ¤¢¤ê
+writepages:
+set_page_dirty ¤¤¤¤¤¨
+readpages:
+write_begin: ¥Ú¡¼¥¸¤ò¥í¥Ã¥¯¤·¤Þ¤¹ ¤Ï¤¤
+write_end: ¤Ï¤¤¡£¥¢¥ó¥í¥Ã¥¯¤·¤Þ¤¹ ¤Ï¤¤
+bmap:
+invalidatepage: ¤Ï¤¤
+releasepage: ¤Ï¤¤
+freepage: ¤Ï¤¤
+direct_IO:
+get_xip_mem: ²ÄǽÀ¤¢¤ê
+migratepage: ¤Ï¤¤ (ξÊý¶¦)
+launder_page: ¤Ï¤¤
+is_partially_uptodate: ¤Ï¤¤
+error_remove_page: ¤Ï¤¤
+swap_activate: ¤¤¤¤¤¨
+swap_deactivate: ¤¤¤¤¤¨
+
+# ->write_begin(), ->write_end(), ->sync_page() and ->readpage()
+#may be called from the request handler (/dev/loop)
+ ->write_begin(), ->write_end(), ->sync_page() ¤ª¤è¤Ó
+ ->readpage() ¤Ï¡¢¥ê¥¯¥¨¥¹¥È¥Ï¥ó¥É¥é (/dev/loop) ¤«¤é¸Æ¤Ð¤ì¤ë²Äǽ
+ À¤¬¤¢¤ê¤Þ¤¹¡£
+
+# ->readpage() unlocks the page, either synchronously or via I/O
+#completion.
+ ->readpage() ¤Ï¡¢Æ±´üŪ¤¢¤ë¤¤¤Ï I/O ´°Î»»þ¤Ë¥Ú¡¼¥¸¤ò¥¢¥ó¥í¥Ã¥¯¤·
+ ¤Þ¤¹¡£
+
+# ->readpages() populates the pagecache with the passed pages and starts
+#I/O against them. They come unlocked upon I/O completion.
+ ->readpages() ¤ÏÅϤµ¤ì¤¿¥Ú¡¼¥¸¤Ç¥Ú¡¼¥¸¥¥ã¥Ã¥·¥å¤òËä¤á¡¢¤½¤ì¤ËÂÐ
+ ¤·¤Æ I/O ¤ò³«»Ï¤·¤Þ¤¹¡£I/O ´°Î»¤Ç¥í¥Ã¥¯¤¬²ò½ü¤µ¤ì¤Þ¤¹¡£
+
+# ->writepage() is used for two purposes: for "memory cleansing" and for
+#"sync". These are quite different operations and the behaviour may differ
+#depending upon the mode.
+ ->writepage() ¤Ë¤ÏÆó¤Ä¤ÎÌÜŪ¤¬¤¢¤ê¤Þ¤¹¡£¤Ò¤È¤Ä¤Ï¡Ö¥á¥â¥ê¾Ãµî¡×¤Ç¡¢
+ ¤â¤¦¤Ò¤È¤Ä¤Ï ¡Ésync" ¤Ç¤¹¡£¤³¤ÎÆó¤Ä¤Ï¤Þ¤Ã¤¿¤¯°Û¤Ê¤Ã¤¿½èÍý¤Ç¡¢µóÆ°
+ ¤â¥â¡¼¥É¤Ë¤è¤Ã¤Æ°Û¤Ê¤ê¤Þ¤¹¡£
+
+#If writepage is called for sync (wbc->sync_mode != WBC_SYNC_NONE) then
+#it *must* start I/O against the page, even if that would involve
+#blocking on in-progress I/O.
+writepage ¤¬ sync ¤Î¤¿¤á¤Ë¸Æ¤Ð¤ì¤¿ (wbc->sync_mode != WBC_SYNC_NONE) ¾ì
+¹ç¡¢¿Ê¹ÔÃæ¤Î I/O ½èÍý¤ò¥Ö¥í¥Ã¥¯¤¹¤ë¤³¤È¤Ë¤Ê¤Ã¤Æ¤â¡¢Âоݥڡ¼¥¸¤ËÂФ·¤Æ I/O
+¤ò³«»Ï¤·¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó¡£
+
+#If writepage is called for memory cleansing (sync_mode ==
+#WBC_SYNC_NONE) then its role is to get as much writeout underway as
+#possible. So writepage should try to avoid blocking against
+#currently-in-progress I/O.
+writepage ¤¬¥á¥â¥ê¾Ãµî¤Î¤¿¤á¤Ë¸Æ¤Ð¤ì¤¿ (sync_mode == WBC_SYNC_NONE) ¾ì¹ç¡¢
+¤½¤ÎÌÜŪ¤Ï²Äǽ¤Ê¸Â¤ê¿¿ô¤Î¿Ê¹ÔÃæ¤Î½ñ¤¹þ¤ß¤ò½èÍý¤¹¤ë¤³¤È¤Ç¤¹¡£½¾¤Ã¤Æ¡¢
+writepage ¤Ï¿Ê¹ÔÃæ¤Î I/O ¤ò¥Ö¥í¥Ã¥¯¤¹¤ë¤³¤È¤òÈò¤±¤ë¤Ù¤¤Ç¤¹¡£
+
+#If the filesystem is not called for "sync" and it determines that it
+#would need to block against in-progress I/O to be able to start new I/O
+#against the page the filesystem should redirty the page with
+#redirty_page_for_writepage(), then unlock the page and return zero.
+#This may also be done to avoid internal deadlocks, but rarely.
+¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬ sync ¤Î¤¿¤á¤Ë¸Æ¤Ð¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¡¢Âоݥڡ¼¥¸¤ËÂФ·¤Æ¿·
+¤·¤¤ I/O ¤ò³«»Ï¤¹¤ë¤¿¤á¤Ë¿Ê¹ÔÃæ¤Î I/O ½èÍý¤ò¥Ö¥í¥Ã¥¯¤¹¤ëɬÍפ¬¤¢¤ë¤ÈȽÃǤµ
+¤ì¤¿¤Ê¤é¤Ð¡¢¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ï redirty_page_for_writepage() ¤ò»È¤Ã¤ÆÂоÝ
+¥Ú¡¼¥¸¤ò dirty ¤ËÌᤷ¤Æ¡¢¤½¤Î¸å¥Ú¡¼¥¸¤ò¥¢¥ó¥í¥Ã¥¯¤·¤ÆÌá¤êÃÍ 0 ¤ÇÌá¤ë¤Ù¤¤Ç¤¹¡£
+¤³¤ì¤ÏÆâÉô¤Î¥Ç¥Ã¥É¥í¥Ã¥¯¤òÈò¤±¤ë¤¿¤á¤Ë¹Ô¤ï¤ì¤ë¾ì¹ç¤â¤¢¤ê¤Þ¤¹¤¬¡¢µ©¤Ç¤·¤ç¤¦¡£
+
+#If the filesystem is called for sync then it must wait on any
+#in-progress I/O and then start new I/O.
+¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬ sync ¤Î¤¿¤á¤Ë¸Æ¤Ð¤ì¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¡¢¿Ê¹ÔÃæ¤Î I/O ¤¬¤¢¤ë
+¾ì¹ç¤Ë¤Ï¤½¤ì¤òÂÔ¤Á¡¢¤½¤Î¸å¤Ç¿·¤·¤¤ I/O ¤ò³«»Ï¤·¤Þ¤¹¡£
+
+#The filesystem should unlock the page synchronously, before returning to the
+#caller, unless ->writepage() returns special WRITEPAGE_ACTIVATE
+#value. WRITEPAGE_ACTIVATE means that page cannot really be written out
+#currently, and VM should stop calling ->writepage() on this page for some
+#time. VM does this by moving page to the head of the active list, hence the
+#name.
+¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ï¡¢->writepage() ¤¬ÆÃÊÌ¤Ê WRITEPAGE_ACTIVATE ÃͤòÊÖ¤·¤Æ
+¤¤¤Ê¤¤¸Â¤ê¡¢Æɤ߽Ф·¸µ¤ËÌá¤ëÁ°¤Ë¥Ú¡¼¥¸¤òƱ´üŪ¤Ë¥¢¥ó¥í¥Ã¥¯¤¹¤Ù¤¤Ç¤¹¡£
+WRITEPAGE_ACTIVATE ¤Ï³ºÅö¥Ú¡¼¥¸¤ò½ñ¤Ì᤹¤³¤È¤¬¸½»þÅÀ¤Ç¤ÏËÜÅö¤Ë¤Ç¤¤º¡¢VM
+¤¬¤½¤Î¥Ú¡¼¥¸¤Ë ->writepage() ¤òȯ¹Ô¤¹¤ë¤Î¤ò°ì»þŪ¤Ë»ß¤á¤ë¤Ù¤¤³¤È¤ò°ÕÌ£¤·
+¤Þ¤¹¡£VM ¤Ï¤³¤Î½èÍý¤ò¡¢Åö³º¥Ú¡¼¥¸¤ò active
+¥ê¥¹¥È¤ÎÀèƬ¤Ë»ý¤Ã¤Æ¤¯¤ë¤³¤È¤Ç¼Â¸½¤·¤Æ¤¤¤ë¤¿¤á¡¢¤³¤Î̾¾Î¤¬ÉÕ¤±¤é¤ì¤Æ¤¤¤Þ¤¹¡£
+
+#Unless the filesystem is going to redirty_page_for_writepage(), unlock the page
+#and return zero, writepage *must* run set_page_writeback() against the page,
+#followed by unlocking it. Once set_page_writeback() has been run against the
+#page, write I/O can be submitted and the write I/O completion handler must run
+#end_page_writeback() once the I/O is complete. If no I/O is submitted, the
+#filesystem must run end_page_writeback() against the page before returning from
+#writepage.
+¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬ redirty_page_for_writepage() ¤ò¹Ô¤Ã¤Æ¡¢¥Ú¡¼¥¸¤ò¥¢¥ó¥í
+¥Ã¥¯¤·¡¢0 ¤òÊÖ¤½¤¦¤È¤·¤Æ¤¤¤ë¤Î¤Ç¤Ï¤Ê¤¤¸Â¤ê¡¢writepage ¤Ï
+set_page_writeback() ¤òÂоݥڡ¼¥¸¤Ëɬ¤º¼Â¹Ô¤·¡¢°ú¤Â³¤¤¤Æ¥¢¥ó¥í¥Ã¥¯¤·¤Ê¤±
+¤ì¤Ð¤¤¤±¤Þ¤»¤ó¡£Åö³º¥Ú¡¼¥¸¤ËÂФ·¤Æ set_page_writeback() ¤ò¼Â¹Ô¤·¤¿¸å¤Ï¡¢write
+I/O ¤òÅêÆþ¤¹¤ë¤³¤È¤¬¤Ç¤¡¢write I/O ´°Î»¥Ï¥ó¥É¥é¤Ï I/O ¤Î´°Î»¸å
+end_page_writeback() ¤ò°ì²ó¼Â¹Ô¤·¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó¡£I/O ¤¬ÅêÆþ¤µ¤ì¤Æ¤¤¤Ê
+¤¤¾ì¹ç¤Ï¡¢¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ï writepage ¤«¤éÌá¤ëÁ°¤ËÂоݥڡ¼¥¸¤Ë
+end_page_writeback() ¤ò¼Â¹Ô¤·¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó¡£
+
+#That is: after 2.5.12, pages which are under writeout are *not* locked. Note,
+#if the filesystem needs the page to be locked during writeout, that is ok, too,
+#the page is allowed to be unlocked at any point in time between the calls to
+#set_page_writeback() and end_page_writeback().
+¤³¤Î¼ñ»Ý¤Ï¡¢2.5.12 °Ê¹ß¤Ç¤Ï¡¢½ñ¤½Ð¤·½èÍýÃæ¤Î¥Ú¡¼¥¸¤Ï¥í¥Ã¥¯¤µ¤ì¤Æ¡ö¤¤¤Ê¤¤¡ö
+¤¿¤á¤Ç¤¹¡£Ãí°Õ¤¬É¬ÍפʤΤϡ¢¤â¤·¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬¥Ú¡¼¥¸¤Î½ñ¤½Ð¤·»þ¤Ë
+¤½¤Î¥Ú¡¼¥¸¤ò¥í¥Ã¥¯¤¹¤ëɬÍפ¬¤¢¤Ã¤¿¾ì¹ç¡¢¤½¤¦¤¹¤ë¤³¤È¤âµö¤µ¤ì¤ë¡¢¤È¤¤¤¦ÅÀ¤Ç¤¹¡£
+¥Ú¡¼¥¸¤Ï set_page_writeback() ¤Î¸Æ¤Ó½Ð¤·¤«¤é end_page_writeback() ¤Î¸Æ¤Ó½Ð¤·
+¤Þ¤Ç¤Î¤É¤Î»þÅÀ¤Ç¥¢¥ó¥í¥Ã¥¯¤¹¤ë¤³¤È¤âµö¤µ¤ì¤Æ¤¤¤ë¤Î¤Ç¤¹¡£
+
+#Note, failure to run either redirty_page_for_writepage() or the combination of
+#set_page_writeback()/end_page_writeback() on a page submitted to writepage
+#will leave the page itself marked clean but it will be tagged as dirty in the
+#radix tree. This incoherency can lead to all sorts of hard-to-debug problems
+#in the filesystem like having dirty inodes at umount and losing written data.
+Ãí°ÕÅÀ¤È¤·¤Æ¡¢redirty_page_for_writepage() ¤Î¼Â¹Ô¤«¡¢
+set_page_writeback()/end_page_writeback() ¤Î¼Â¹Ô¤ÎÁȤ߹ç¤ï¤»¤Î¤É¤Á¤é¤«¤Ç
+writepage ÅêÆþ¤¬¼ºÇÔ¤·¤¿¥Ú¡¼¥¸¤Ï¡¢radix ¥Ä¥ê¡¼¾å¤Ç¥À¡¼¥Æ¥£¤Ë¥¿¥°ÉÕ¤±¤é¤ì¤Æ
+¤¤¤ë¤Î¤Ë¤½¤ì¼«ÂΤϥ¯¥ê¡¼¥ó¤È¥Þ¡¼¥¯¤µ¤ì¤Æ¤¤¤ë¾õÂ֤ǻĤë²ÄǽÀ¤¬¤¢¤ë¤³¤È¤Ç¤¹¡£
+¤³¤ÎÉÔ°ìÃפϡ¢¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ë¤¢¤é¤æ¤ë¼ïÎà¤Î¥Ç¥Ð¥Ã¥°º¤Æñ¤ÊÌäÂê¡¢Î㤨¤Ð¥À
+¡¼¥Æ¥£¥Ú¡¼¥¸¤¬¥¢¥ó¥Þ¥¦¥ó¥È»þ¤Ë»Ä¤Ã¤Æ¡¢½ñ¤¹þ¤ß¥Ç¡¼¥¿¤¬¾Ã¼º¤·¤¿¤ê¤¹¤ë¤Ê¤É¡¢
+¤ò°ú¤µ¯¤³¤·¤Þ¤¹¡£
+
+# ->sync_page() locking rules are not well-defined - usually it is called
+#with lock on page, but that is not guaranteed. Considering the currently
+#existing instances of this method ->sync_page() itself doesn't look
+#well-defined...
+ ->sync_page() ¤Î¥í¥Ã¥¯µ¬Â§¤ÏÌÀ³Î¤Ë¤ÏÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó¡£¤³¤Î´Ø¿ô
+ ¤ÏÄ̾ï¥Ú¡¼¥¸¤Î¥í¥Ã¥¯¤ò»ý¤Ã¤¿¾õÂ֤ǸƤФì¤Þ¤¹¤¬¡¢¤½¤Î¤³¤È¤ÏÊݾڤµ
+ ¤ì¤Æ¤Ï¤¤¤Þ¤»¤ó¡£´û¸¤Î¡¢¤³¤Î¥á¥½¥Ã¥É¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤«¤éȽÃǤ¹¤ë¸Â¤ê¡¢
+ ¤½¤â¤½¤â sync_page() ¼«ÂΤ¬ÌÀ³Î¤ËÄêµÁ¤µ¤ì¤Æ¤Ï¤¤¤Ê¤¤¤è¤¦¤Ç¤¹¡£
+
+# ->writepages() is used for periodic writeback and for syscall-initiated
+#sync operations. The address_space should start I/O against at least
+#*nr_to_write pages. *nr_to_write must be decremented for each page which is
+#written. The address_space implementation may write more (or less) pages
+#than *nr_to_write asks for, but it should try to be reasonably close. If
+#nr_to_write is NULL, all dirty pages must be written.
+ ->writepages() ¤ÏÄê´üŪ¤Ê¥é¥¤¥È¥Ð¥Ã¥¯¤È¡¢syscall ¤Çµ¯Æ°¤µ¤ì¤ë
+ sync ½èÍý¤ËÍѤ¤¤é¤ì¤Þ¤¹¡£¥¢¥É¥ì¥¹¶õ´Ö¤Ç¤Ï¡¢¾¯¤Ê¤¯¤È¤â
+ *nr_to_write ¿ô¤Î¥Ú¡¼¥¸¤ËÂФ·¤Æ I/O ¤ò³«»Ï¤¹¤Ù¤¤Ç¡¢¥Ú¡¼¥¸¤¬½ñ¤
+ ¹þ¤Þ¤ì¤ëÅÙ¤Ë *nr_to_write ¤«¤é 1 ¤Å¤Ä°ú¤¤¤Æ¤¤¤¤Þ¤¹¡£¥¢¥É¥ì¥¹¶õ´Ö
+ ½èÍý¤Î¼ÂÁõ¤Ç¤Ï¡¢Í׵ᤵ¤ì¤¿ *nr_to_write °Ê¾å (¤Þ¤¿¤Ï°Ê²¼) ¤Î¥Ú¡¼
+ ¥¸¤ò½ñ¤¹þ¤à¼ÂÁõ¤È¤¹¤ë¤³¤È¤Ï¤Ç¤¤Þ¤¹¤¬¡¢ÂÅÅö¤ÊÈϰϤǶᤤ¿ô¤Î½èÍý¤ò¤ª¤³¤Ê
+ ¤¦¤è¤¦´èÄ¥¤ë¤Ù¤¤Ç¤¹¡£nr_to_write ¤¬ NULL ¤Î¾ì¹ç¤Ï¡¢Á´¤Æ¤Î¥À¡¼¥Æ
+ ¥£¥Ú¡¼¥¸¤ò½ñ¤¹þ¤Þ¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó¡£
+
+#writepages should _only_ write pages which are present on
+#mapping->io_pages.
+writepages ¤Ï¡¢mapping->io_pages ¤Ë¸ºß¤¹¤ë¥Ú¡¼¥¸¡ö¤Î¤ß¡ö¤ò½ñ¤¹þ¤à¤è¤¦
+¤Ë¤¹¤Ù¤¤Ç¤¹¡£
+
+# ->set_page_dirty() is called from various places in the kernel
+#when the target page is marked as needing writeback. It may be called
+#under spinlock (it cannot block) and is sometimes called with the page
+#not locked.
+ ->set_page_dirty() ¤Ï¡¢ÂоݤȤʤë¥Ú¡¼¥¸¤ò½ñ¤¹þ¤à¤Ù¤¤Ç¤¢¤ë¤È¥Þ¡¼
+ ¥¥ó¥°¤¹¤ëÌÜŪ¤Ç¡¢¥«¡¼¥Í¥ë¤ÎÍÍ¡¹¤Ê²Õ½ê¤«¤é¸Æ¤Ð¤ì¤Þ¤¹¡£¤³¤ì¤Ï
+ spinlock ¾õÂÖ¤«¤é¸Æ¤Ö¤³¤È¤â¤Ç¤¤Þ¤¹¤· (¥Ö¥í¥Ã¥¯ÉԲĤǤ¹)¡¢¥í¥Ã¥¯
+ ¤µ¤ì¤Æ¤¤¤Ê¤¤¥Ú¡¼¥¸¤ËÂФ·¤Æ¸Æ¤Ö¤³¤È¤â»þ¡¹¤¢¤ê¤Þ¤¹¡£
+
+# ->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some
+#filesystems and by the swapper. The latter will eventually go away. Please,
+#keep it that way and don't breed new callers.
+ ->bmap() ¤Ï¸½ºß¤Î¤È¤³¤í¡¢°ìÉô¤Î¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë½¾Íè
+ ¸ß´¹ ioctl() (FIBMAP) ¤È¥¹¥ï¥Ã¥Ñ¤Ç»È¤ï¤ì¤Æ¤¤¤Þ¤¹¡£¸å¼Ô¤ÎÍøÍѤÏ
+ ¾Íè¾ÃÌÇÊý¸þ¤Ç¤¹¡£¤³¤ÎÊý¸þÀ¤ò¼é¤Ã¤Æ¡¢¿·µ¬¤ÎÍøÍѤò¹Ô¤ï¤Ê¤¤¤è¤¦¤Ë¤·
+ ¤Æ¤¯¤À¤µ¤¤¡£
+
+# ->invalidatepage() is called when the filesystem must attempt to drop
+#some or all of the buffers from the page when it is being truncated. It
+#returns zero on success. If ->invalidatepage is zero, the kernel uses
+#block_invalidatepage() instead.
+ ->invalidatepage() ¤Ï¡¢¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬¥Ú¡¼¥¸¤«¤é°ìÉô¤¢¤ë¤¤¤ÏÁ´
+ ¤Æ¤Î¥Ð¥Ã¥Õ¥¡¤ò¡¢¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤Î½Ì¾®¤Ëȼ¤Ã¤Æ¼Î¤Æ¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¾ì
+ ¹ç¤Ë¸Æ¤Ð¤ì¤Þ¤¹¡£À®¸ù»þ¤Ë¤Ï 0 ¤¬ÊÖ¤ê¤Þ¤¹¡£¤â¤· ->invalidatepage ¤¬
+ 0 ¤Ê¤é¤Ð¡¢¥«¡¼¥Í¥ë¤Ï block_invalidatepage() ¤òÂå¤ï¤ê¤Ë»ÈÍѤ·¤Þ¤¹¡£
+
+# ->releasepage() is called when the kernel is about to try to drop the
+#buffers from the page in preparation for freeing it. It returns zero to
+#indicate that the buffers are (or may be) freeable. If ->releasepage is zero,
+#the kernel assumes that the fs has no private interest in the buffers.
+ ->releasepage() ¤Ï¡¢¥«¡¼¥Í¥ë¤¬¥Ú¡¼¥¸²òÊü¤Î½àÈ÷¤Î¤¿¤á¥Ú¡¼¥¸¤«¤é¥Ð
+ ¥Ã¥Õ¥¡¤ò¼Î¤Æ¤è¤¦¤È¤¹¤ëºÝ¤Ë¸Æ¤Ð¤ì¤Þ¤¹¡£¥Ð¥Ã¥Õ¥¡¤¬²òÊü²Äǽ¤Ç¤¢¤ë (¤È
+ ¹Í¤¨¤é¤ì¤ë) ¾ì¹ç¡¢0 ¤¬ÊÖ¤ê¤Þ¤¹¡£->releasepage ¤¬ 0 ¤Î¾ì¹ç¡¢¥«¡¼
+ ¥Í¥ë¤Ï¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬¥Ð¥Ã¥Õ¥¡¤ËÂФ·¤Æ¸ÄÊ̤ÎÍ×µá»ö¹à¤ò»ý¤Ã¤Æ¤¤¤Ê
+ ¤¤¤ÈȽÃǤ·¤Þ¤¹¡£
+
+# ->freepage() is called when the kernel is done dropping the page
+#from the page cache.
+ ->freepage() ¤Ï¡¢¥«¡¼¥Í¥ë¤¬¥Ú¡¼¥¸¥¥ã¥Ã¥·¥å¤«¤é¤Î¥Ú¡¼¥¸ºï½ü¤ò´°Î»¤·
+ ¤¿¸å¸Æ¤Ð¤ì¤Þ¤¹¡£
+
+# ->launder_page() may be called prior to releasing a page if
+#it is still found to be dirty. It returns zero if the page was successfully
+#cleaned, or an error value if not. Note that in order to prevent the page
+#getting mapped back in and redirtied, it needs to be kept locked
+#across the entire operation.
+ ->launder_page() ¤Ï¡¢¥À¡¼¥Æ¥£¤Ç¤¢¤ë¤³¤È¤¬È¯¸«¤µ¤ì¤¿¥Ú¡¼¥¸¤Î²òÊü¤Ë
+ ÀèΩ¤Ã¤Æ¸Æ¤Ö¤³¤È¤¬¤Ç¤¤Þ¤¹¡£¼óÈøÎɤ¯¥¯¥ê¡¼¥ó¤Ë¤¹¤ë¤³¤È¤¬¤Ç¤¤¿¾ì¹ç
+ 0 ¤òÊÖ¤·¡¢¤Ç¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¨¥é¡¼¤òÊÖ¤·¤Þ¤¹¡£¥Ú¡¼¥¸¤¬ºÆ¥Þ¥Ã¥×¤µ
+ ¤ì¤ÆºÆÅÙ¥À¡¼¥Æ¥£¤ËÌᤵ¤ì¤ë¤³¤È¤òÈò¤±¤ë¤¿¤á¡¢½èÍýÁ´ÂΤǥí¥Ã¥¯¤ò¤È¤Ã
+ ¤¿¤Þ¤Þ¤Ë¤·¤Æ¤ª¤¯É¬Íפ¬¤¢¤ê¤Þ¤¹¡£
+
+# ->swap_activate will be called with a non-zero argument on
+#files backing (non block device backed) swapfiles. A return value
+#of zero indicates success, in which case this file can be used for
+#backing swapspace. The swapspace operations will be proxied to the
+#address space operations.
+ ->swap_activate ¤Ï¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤È¤·¤Æ»È¤¦¥Õ¥¡¥¤¥ë (¥Ö¥í¥Ã¥¯¥Ç¥Ð
+ ¥¤¥¹¤Ç¤Ï¤Ê¤¤¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë) ¤ËÂФ·¡¢0 °Ê³°¤Î°ú¿ô¤Ç¸Æ¤Ð¤ì¤Þ¤¹¡£0
+ °Ê³°¤ÎÌá¤êÃͤϸƤӽФ·¤¬À®¸ù¤·¤¿¤³¤È¤ò¼¨¤·¡¢¤³¤Î¥Õ¥¡¥¤¥ë¤ò¥¹¥ï¥Ã¥×
+ ¶õ´ÖÍѤȤ·¤Æ»È¤¦¤³¤È¤¬¤Ç¤¤Þ¤¹¡£¥¹¥ï¥Ã¥×¶õ´Ö½èÍý¤Ï¡¢¥¢¥É¥ì¥¹¶õ´Ö½è
+ Íý¤ÇÂå¹Ô¤µ¤ì¤Þ¤¹¡£
+
+# ->swap_deactivate() will be called in the sys_swapoff()
+#path after ->swap_activate() returned success.
+ ->swap_deactivate() ¤Ï¡¢sys_swapoff() ¥Ñ¥¹Æâ¤Ç¡¢->swap_activate()
+ ¸Æ¤Ó½Ð¤·¤ÎÀ®¸ù¸å¤Ë¸Æ¤Ð¤ì¤Þ¤¹¡£
+
+----------------------- file_lock_operations ------------------------------
+prototypes:
+ void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
+ void (*fl_release_private)(struct file_lock *);
+
+
+#locking rules:
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë:
+# file_lock_lock may block
+#fl_copy_lock: yes no
+#fl_release_private: maybe no
+ file_lock_lock ¥Ö¥í¥Ã¥¯¤Î²ÄǽÀ
+fl_copy_lock: ¤Ï¤¤ ¤¤¤¤¤¨
+fl_release_private: ²ÄǽÀ¤¢¤ê ¤¤¤¤¤¨
+
+----------------------- lock_manager_operations ---------------------------
+prototypes:
+ int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
+ void (*lm_notify)(struct file_lock *); /* unblock callback */
+ int (*lm_grant)(struct file_lock *, struct file_lock *, int);
+ void (*lm_break)(struct file_lock *); /* break_lease callback */
+ int (*lm_change)(struct file_lock **, int);
+
+#locking rules:
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë:
+# file_lock_lock may block
+#lm_compare_owner: yes no
+#lm_notify: yes no
+#lm_grant: no no
+#lm_break: yes no
+#lm_change yes no
+ file_lock_lock ¥Ö¥í¥Ã¥¯¤Î²ÄǽÀ
+lm_compare_owner: ¤Ï¤¤ ¤¤¤¤¤¨
+lm_notify: ¤Ï¤¤ ¤¤¤¤¤¨
+lm_grant: ¤¤¤¤¤¨ ¤¤¤¤¤¨
+lm_break: ¤Ï¤¤ ¤¤¤¤¤¨
+lm_change ¤Ï¤¤ ¤¤¤¤¤¨
+
+--------------------------- buffer_head -----------------------------------
+prototypes:
+ void (*b_end_io)(struct buffer_head *bh, int uptodate);
+
+#locking rules:
+# called from interrupts. In other words, extreme care is needed here.
+#bh is locked, but that's all warranties we have here. Currently only RAID1,
+#highmem, fs/buffer.c, and fs/ntfs/aops.c are providing these. Block devices
+#call this method upon the IO completion.
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë:
+ ³ä¤ê¹þ¤ß½èÍý¤«¤é¸Æ¤Ð¤ì¤Þ¤¹¡£¸À¤¤Êý¤òÊѤ¨¤ë¤È¡¢¤³¤³¤Ç¤ÏºÙ¿´¤ÎÃí°Õ¤¬
+ ɬÍפǤ¹¡£bh ¤Ï¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤¹¤¬¡¢¤³¤³¤Ç¤Ï¤½¤ì¤¬Í£°ì¤ÎÊݸî¤È¤¤
+ ¤¦¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡£¸½ºß RAID1, highmem, fs/buffer.c ¤È
+ fs/nfs/app.c ¤¬Ëܵ¡Ç½¤òÄ󶡤·¤Æ¤¤¤Þ¤¹¡£¥Ö¥í¥Ã¥¯¥Ç¥Ð¥¤¥¹¤Ï I/O ´°
+ λ»þ¤Ë¤³¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤·¤Þ¤¹¡£
+
+--------------------------- block_device_operations -----------------------
+prototypes:
+ int (*open) (struct block_device *, fmode_t);
+ int (*release) (struct gendisk *, fmode_t);
+ int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
+ int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
+ int (*direct_access) (struct block_device *, sector_t, void **, unsigned long *);
+ int (*media_changed) (struct gendisk *);
+ void (*unlock_native_capacity) (struct gendisk *);
+ int (*revalidate_disk) (struct gendisk *);
+ int (*getgeo)(struct block_device *, struct hd_geometry *);
+ void (*swap_slot_free_notify) (struct block_device *, unsigned long);
+
+#locking rules:
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë:
+ bd_mutex
+#open: yes
+#release: yes
+#ioctl: no
+#compat_ioctl: no
+#direct_access: no
+#media_changed: no
+#unlock_native_capacity: no
+#revalidate_disk: no
+#getgeo: no
+#swap_slot_free_notify: no (see below)
+open: ¤Ï¤¤
+release: ¤Ï¤¤
+ioctl: ¤¤¤¤¤¨
+compat_ioctl: ¤¤¤¤¤¨
+direct_access: ¤¤¤¤¤¨
+media_changed: ¤¤¤¤¤¨
+unlock_native_capacity: ¤¤¤¤¤¨
+revalidate_disk: ¤¤¤¤¤¨
+getgeo: ¤¤¤¤¤¨
+swap_slot_free_notify: ¤¤¤¤¤¨ (²¼µ»²¾È)
+
+#media_changed, unlock_native_capacity and revalidate_disk are called only from
+#check_disk_change().
+media_changed¡¢unlock_native_capacity¡¢revalidate_disk ¤Ï
+check_disk_change() ¤«¤é¤Î¤ß¸Æ¤Ð¤ì¤Þ¤¹¡£
+
+#swap_slot_free_notify is called with swap_lock and sometimes the page lock
+#held.
+swap_slot_free_notify ¤Ï swap_lock ¤òÊÝ»ý¤·¤¿¾õÂ֤ǸƤФ졢¥Ú¡¼¥¸¥í¥Ã¥¯¤ò
+ÊÝ»ý¤·¤Æ¤¤¤ë¾ì¹ç¤â¤¢¤ê¤Þ¤¹¡£
+
+--------------------------- file_operations -------------------------------
+prototypes:
+ 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 (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ int (*readdir) (struct file *, void *, filldir_t);
+ unsigned int (*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 *);
+ int (*open) (struct inode *, struct file *);
+ int (*flush) (struct file *);
+ int (*release) (struct inode *, struct file *);
+ int (*fsync) (struct file *, loff_t start, loff_t end, int datasync);
+ int (*aio_fsync) (struct kiocb *, int datasync);
+ int (*fasync) (int, struct file *, int);
+ int (*lock) (struct file *, int, struct file_lock *);
+ ssize_t (*readv) (struct file *, const struct iovec *, unsigned long,
+ loff_t *);
+ ssize_t (*writev) (struct file *, const struct iovec *, unsigned long,
+ loff_t *);
+ ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t,
+ void __user *);
+ 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 **);
+ long (*fallocate)(struct file *, int, loff_t, loff_t);
+};
+
+#locking rules:
+# All may block except for ->setlease.
+# No VFS locks held on entry except for ->setlease.
+#
+#->setlease has the file_list_lock held and must not sleep.
+# All except ->poll() may block.
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë:
+ ->setlease °Ê³°¤Ï¥Ö¥í¥Ã¥¯¤Î²ÄǽÀ¤¬¤¢¤ê¤Þ¤¹¡£
+ ->setlease °Ê³°¤Ï¡¢¸Æ¤Ó½Ð¤·»þ¤Ë VFS ¥í¥Ã¥¯¤òÊÝ»ý¤·¤Þ¤»¤ó¡£
+
+->setlease ¤Ï¡¢file_list_lock ¤òÊÝ»ý¤·¤Æ¸Æ¤Ð¤ì¡¢sleep ¤·¤Æ¤Ï¤¤¤±¤Þ¤»¤ó¡£
+
+#->llseek() locking has moved from llseek to the individual llseek
+#implementations. If your fs is not using generic_file_llseek, you
+#need to acquire and release the appropriate locks in your ->llseek().
+#For many filesystems, it is probably safe to acquire the inode
+#mutex or just to use i_size_read() instead.
+#Note: this does not protect the file->f_pos against concurrent modifications
+#since this is something the userspace has to take care about.
+->llseek() ¥í¥Ã¥¯½èÍý¤Ï llseek ¼«ÂΤ«¤é¡¢¸Ä¡¹¤Î llseek ¤Î¼ÂÁõ¦¤Ë°Ü¤µ¤ì¤Þ
+¤·¤¿¡£ºîÀ®¤·¤Æ¤¤¤ë¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬ generic_file_llseek() ¤ò»È¤Ã¤Æ¤¤¤Ê¤¤
+¤Ê¤é¡¢¼«Ê¬¤Î ->llseek() ¼ÂÁõÃæ¤ÇɬÍפʥí¥Ã¥¯¤Î¼èÆÀ¤È²òÊü¤ò¹Ô¤¦É¬Íפ¬¤¢¤ê¤Þ
+¤¹¡£Â¿¤¯¤Î¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ç¤Ï¡¢inode mutex ¤ò³ÎÊݤ¹¤ë½èÍý¡¢¤ª¤è¤ÓÂå¤ï¤ê¤Ë
+ñ¤Ë i_size_read() ¤ò»È¤¦½èÍý¤Ï¤ª¤½¤é¤¯°ÂÁ´¤Ç¤¹¡£
+
+Ãí°Õ: ¤³¤Î½èÍý¤Ç¤Ï¡¢file->f_pos ¤¬Æ±»þ¤Ë¹¹¿·¤µ¤ì¤ë¾ì¹ç¤ÎÊݸî¤ò¹Ô¤¤¤Þ¤»¤ó¡£
+ ¤½¤Î¤è¤¦¤ÊÊݸî¤Ï¡¢¥æ¡¼¥¶¶õ´Ö¦¤Ç¹Íθ¤¹¤Ù¤¤â¤Î¤Ç¤¢¤ë¤¿¤á¤Ç¤¹¡£
+
+#->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags.
+#Most instances call fasync_helper(), which does that maintenance, so it's
+#not normally something one needs to worry about. Return values > 0 will be
+#mapped to zero in the VFS layer.
+
+->fasync() ¤Ï¡¢filp->f_flags Ãæ¤Î FASYNC ¥Ó¥Ã¥È¤ò°Ý»ý¤¹¤ëÀÕǤ¤òÉ餤¤Þ¤¹¡£
+¤Û¤È¤ó¤É¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Ç¤Ï¥á¥ó¥Æ¥Ê¥ó¥¹¤ò¹Ô¤¦ fasync_helper() ¤ò»È¤Ã¤Æ¤ª¤ê¡¢
+ÉáÄ̤Ϥ¢¤Þ¤ê¿´ÇÛ¤¹¤ëɬÍפϤʤ¤»ö¹à¤Ç¤¹¡£Ìá¤êÃͤ¬ ¡ä0 ¤Î¾ì¹ç¤Ï VFS ¥ì¥¤¥ä¤Ç
+0 ¤Ë¥Þ¥Ã¥×¤µ¤ì¤Æ¤¤¤Þ¤¹¡£
+
+#->readdir() and ->ioctl() on directories must be changed. Ideally we would
+#move ->readdir() to inode_operations and use a separate method for directory
+#->ioctl() or kill the latter completely. One of the problems is that for
+#anything that resembles union-mount we won't have a struct file for all
+#components. And there are other reasons why the current interface is a mess...
+¥Ç¥£¥ì¥¯¥È¥ê¤Ë´Ø¤¹¤ë ->readdir() ¤È ->ioctl() ¤Ë¤ÏÊѹ¹¤¬É¬ÍפǤ¹¡£ÍýÁÛŪ¤Ë
+¤Ï¡¢readdir() ¤ò inode_operation ¦¤Ë°Ü¤·¤Æ¡¢¥Ç¥£¥ì¥¯¥È¥ê¤Î ->ioctl() ¤Ë
+¤ÏÆÈΩ¤·¤¿¥á¥½¥Ã¥É¤òÍѤ¤¤ë¤«¡¢(¥Ç¥£¥ì¥¯¥È¥ê¤Î ->ioctl() ¤ò) ´°Á´¤Ë»ß¤á¤Ë¤·
+¤Æ¤·¤Þ¤¦¤«¤Ç¤¹¡£¤½¤¦¤·¤¿¾ì¹ç¤ÎÌäÂêÅÀ¤Î°ì¤Ä¤Ï¡¢union-mount ¤ÎÎà¤Î¤â¤Î¤Ë¤Ä¤¤
+¤Æ¤ÏÁ´¤Æ¤Î¥³¥ó¥Ý¡¼¥Í¥ó¥È¤Î¹½Â¤ÂΤ¬¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¦¤³¤È¤Ç¤¹¡£¤³¤ì°Ê³°¤Ë¤â°ì
+ÇÕÍýͳ¤¬¤¢¤Ã¤Æ¡¢¸½ºß¤Î¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤Ï¤°¤Á¤ã¤°¤Á¤ã¤È¤·¤«»×¤¨¤Þ¤»¤ó ¡Ä¡Ä
+
+#->read on directories probably must go away - we should just enforce -EISDIR
+#in sys_read() and friends.
+¥Ç¥£¥ì¥¯¥È¥ê¤ËÂФ¹¤ë ->read ¤Ï¼Î¤Æ¤ë¤Ù¤¤Ê¤Î¤Ç¤·¤ç¤¦¡£Ã±¤Ë sys_read() ¤È
+¤½¤Î¤ªÃç´Ö¤Ç¤Ï -EISDIR ¤ò»È¤¦¤è¤¦¶¯¤¯¿ä¾©¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡£
+
+--------------------------- dquot_operations -------------------------------
+prototypes:
+ int (*write_dquot) (struct dquot *);
+ int (*acquire_dquot) (struct dquot *);
+ int (*release_dquot) (struct dquot *);
+ int (*mark_dirty) (struct dquot *);
+ int (*write_info) (struct super_block *, int);
+
+#These operations are intended to be more or less wrapping functions that ensure
+#a proper locking wrt the filesystem and call the generic quota operations.
+¤³¤ì¤é¤Î½èÍý¤ÏŬÀڤʥí¥Ã¥¥ó¥°¼ê½ç¤òÊݾڤ·¡¢ÈÆÍѤΥ¯¥ª¡¼¥¿½èÍý¤ò¸Æ¤Ö¤è¤¦
+¤Ë¤Ê¤Ã¤Æ¤¤¤ë¥é¥Ã¥Ñ¡¼´Ø¿ô¤ÎÎà¤Ç¤¢¤ë¤³¤È¤ò°Õ¿Þ¤·¤Æ¤¤¤Þ¤¹¡£
+
+#What filesystem should expect from the generic quota functions:
+¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬¡¢ÈÆÍѤΥ¯¥ª¡¼¥¿´Ø¿ô¤ËÂФ·¤ÆÁÛÄꤷ¤Æ¤¤¤ë¤Î¤Ï²¼µ¤Î
+µóÆ°¤Ç¤¹¡£
+
+# FS recursion Held locks when called
+#write_dquot: yes dqonoff_sem or dqptr_sem
+#acquire_dquot: yes dqonoff_sem or dqptr_sem
+#release_dquot: yes dqonoff_sem or dqptr_sem
+#mark_dirty: no -
+#write_info: yes dqonoff_sem
+ FS ºÆµ¢ ¸Æ¤Ð¤ì¤ë¤È¤ÊÝ»ý¤·¤Æ¤¤¤ë¥í¥Ã¥¯
+write_dquot: ¤Ï¤¤ dqonoff_sem ¤Þ¤¿¤Ï dqptr_sem
+acquire_dquot: ¤Ï¤¤ dqonoff_sem ¤Þ¤¿¤Ï dqptr_sem
+release_dquot: ¤Ï¤¤ dqonoff_sem ¤Þ¤¿¤Ï dqptr_sem
+mark_dirty: ¤¤¤¤¤¨ -
+write_info: ¤Ï¤¤ dqonoff_sem
+
+#FS recursion means calling ->quota_read() and ->quota_write() from superblock
+#operations.
+FS ºÆµ¢¤È¤Ï¡¢->quota_read() ¤ä ->quota_write() ¤ò¥¹¡¼¥Ñ¡¼¥Ö¥í¥Ã¥¯Áàºî¤«¤é
+¸Æ¤Ö¤³¤È¤Ç¤¹¡£
+
+#More details about quota locking can be found in fs/dquot.c.
+¥¯¥ª¡¼¥¿¥í¥Ã¥¯½èÍý¤Î¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï¡¢fs/dquot.c ¤ËµºÜ¤µ¤ì¤Æ¤¤¤Þ¤¹¡£
+
+--------------------------- vm_operations_struct -----------------------------
+prototypes:
+ void (*open)(struct vm_area_struct*);
+ void (*close)(struct vm_area_struct*);
+ int (*fault)(struct vm_area_struct*, struct vm_fault *);
+ int (*page_mkwrite)(struct vm_area_struct *, struct vm_fault *);
+ int (*access)(struct vm_area_struct *, unsigned long, void*, int, int);
+
+#locking rules:
+# mmap_sem PageLocked(page)
+#open: yes
+#close: yes
+#fault: yes can return with page locked
+#page_mkwrite: yes can return with page locked
+#access: yes
+¥í¥Ã¥¥ó¥°¥ë¡¼¥ë:
+ mmap_sem PageLocked(¥Ú¡¼¥¸)
+open: ¤Ï¤¤
+close: ¤Ï¤¤
+fault: ¤Ï¤¤ ¥Ú¡¼¥¸¤ò¥í¥Ã¥¯¤·¤¿¤Þ¤ÞÌá¤Ã¤Æ¤â¤è¤¤
+page_mkwrite: ¤Ï¤¤ ¥Ú¡¼¥¸¤ò¥í¥Ã¥¯¤·¤¿¤Þ¤ÞÌá¤Ã¤Æ¤â¤è¤¤
+access: ¤Ï¤¤
+
+# ->fault() is called when a previously not present pte is about
+#to be faulted in. The filesystem must find and return the page associated
+#with the passed in "pgoff" in the vm_fault structure. If it is possible that
+#the page may be truncated and/or invalidated, then the filesystem must lock
+#the page, then ensure it is not already truncated (the page lock will block
+#subsequent truncate), and then return with VM_FAULT_LOCKED, and the page
+#locked. The VM will unlock the page.
+ ->fault() ¤Ï¡¢°ÊÁ°Â¸ºß¤·¤Ê¤«¤Ã¤¿ pte ¤ò¥Õ¥©¡¼¥ë¥È¤È¤·¤Æ¼è¤ê¹þ¤â¤¦
+ ¤È¤¹¤ëºÝ¤Ë¸Æ¤Ð¤ì¤Þ¤¹¡£¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ï vm_fault ¹½Â¤ÂÎÃæ¤Ç
+ pgoff ¤È¤·¤ÆÅϤµ¤ì¤¿Âбþ¥Ú¡¼¥¸¤òȯ¸«¤·¤Æ¡¢¤½¤Î¥Ú¡¼¥¸¤ò»ý¤Ã¤ÆÌá¤é¤Ê
+ ¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó¡£¥Ú¡¼¥¸¤¬ÀÚ¤êµÍ¤á¤é¤ì¤Æ¤¤¤¿¤ê (truncate)¡¢Ìµ¸ú¤Ë
+ ¤Ê¤Ã¤Æ¤¤¤ë²ÄǽÀ¤¬¤¢¤ê¤Þ¤¹¤¬¡¢¤½¤Î¾ì¹ç¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ï¥Ú¡¼¥¸¤òɬ
+ ¤º¥í¥Ã¥¯¤·¡¢¤½¤ì¤Þ¤Ç¤ËÀÚ¤ê¼Î¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò³Îǧ (¥Ú¡¼¥¸¥í¥Ã¥¯
+ ¤Ë¤è¤ê¸å³¤ÎÀÚ¤ê¼Î¤Æ¤Ï¥Ö¥í¥Ã¥¯¤µ¤ì¤Þ¤¹) ¤·¡¢¥Ú¡¼¥¸¤ò¥í¥Ã¥¯¤·¤¿¾õÂÖ
+ ¤Ç VM_FAULT_LOCKED ¤ÇÊÖ¤é¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡£VM ¤¬¥Ú¡¼¥¸¤ò¤½¤Î¸å
+ ¤Ç¥¢¥ó¥í¥Ã¥¯¤·¤Þ¤¹¡£
+
+# ->page_mkwrite() is called when a previously read-only pte is
+#about to become writeable. The filesystem again must ensure that there are
+#no truncate/invalidate races, and then return with the page locked. If
+#the page has been truncated, the filesystem should not look up a new page
+#like the ->fault() handler, but simply return with VM_FAULT_NOPAGE, which
+#will cause the VM to retry the fault.
+ ->page_mkwrite() ¤Ï¡¢°ÊÁ°Æɤ߽Ф·¤Î¤ß¤À¤Ã¤¿ pte ¤ò½ñ¤¹þ¤ß²Äǽ¤Ë¤·
+ ¤è¤¦¤È¤¹¤ëºÝ¤Ë¸Æ¤Ð¤ì¤Þ¤¹¡£¤³¤³¤Ç¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤ÏºÆÅÙ
+ truncate/invalidate ¶¥¹ç¤¬¤Ê¤¤¤³¤È¤òɬ¤º³Îǧ¤·¡¢¥Ú¡¼¥¸¤ò¥í¥Ã¥¯¤·¤Æ
+ Ìá¤ê¤Þ¤¹¡£¤â¤·¥Ú¡¼¥¸¤¬ÀÚ¤êµÍ¤á¤é¤ì¤Æ¤¤¤ë (truncate) ¾ì¹ç¡¢¥Õ¥¡¥¤¥ë
+ ¥·¥¹¥Æ¥à¤Ï ->fault() ¥Ï¥ó¥É¥é¤È¤Ï°Û¤Ê¤ê¿·¤·¤¤¥Ú¡¼¥¸¤òõ¤µ¤º¤Ë
+ VM_FAULT_NOPAGE ¤ÇÊÖ¤ë¤Ù¤¤Ç¤¹¡£¤³¤ì¤Ë¤è¤ê VM ¤Ï¥Õ¥©¡¼¥ë¥È½èÍý¤ò
+ ¥ê¥È¥é¥¤¤·¤Þ¤¹¡£
+
+# ->access() is called when get_user_pages() fails in
+#acces_process_vm(), typically used to debug a process through
+#/proc/pid/mem or ptrace. This function is needed only for
+#VM_IO | VM_PFNMAP VMAs.
+ ->access() ¤Ï get_user_pages() ¤¬ access_process_vm() Ãæ¤Ç¼ºÇÔ
+ ¤·¤¿¾ì¹ç¡¢Åµ·¿Åª¤Ë¤Ï /proc/pid/mem ¤ä ptrace ¤ò»È¤Ã¤Æ¥×¥í¥»¥¹¤Î¥Ç
+ ¥Ð¥Ã¥°¤ò¹Ô¤Ã¤Æ¤¤¤ë¾ì¹ç¡¢¤Ë¸Æ¤Ð¤ì¤Þ¤¹¡£¤³¤Î´Ø¿ô¤Ï VM_IO | VM_PFNMAP
+ VMA ¤Ç¤Î¤ßɬÍפǤ¹¡£
+
+================================================================================
+# Dubious stuff
+ µ¿¤ï¤·¤¤¾ì¹ç
+
+#(if you break something or notice that it is broken and do not fix it yourself
+#- at least put it here)
+(²¿¤«¤ò²õ¤·¤¿¤«¡¢²¿¤«¤¬²õ¤ì¤Æ¤¤¤ë¤³¤È¤Ëµ¤¤¬¤Ä¤¤¤Æ¡¢¼«Ê¬¤Ç¤½¤ì¤òľ¤µ¤Ê¤¤¾ì¹ç
+¤Ï - ¾¯¤Ê¤¯¤È¤â¤³¤³¤ËµºÜ¤·¤Æ¤¯¤À¤µ¤¤)
+
+