From: Alexey Zaytsev <alexey.zaytsev@gmail.com>
To: Eric Paris <eparis@redhat.com>
Cc: Scott Hassan <hassan@dotfunk.com>, Jan Kara <jack@suse.cz>,
agruen@linbit.com, linux-kernel@vger.kernel.org,
stefan@buettcher.org, Al Viro <viro@zeniv.linux.org.uk>,
linux-fsdevel@vger.kernel.org,
Tvrtko Ursulin <tvrtko.ursulin@sophos.com>
Subject: [PATCH 3/4] fsnotify: Handle the file change ranges
Date: Mon, 22 Nov 2010 00:33:49 +0000 [thread overview]
Message-ID: <20101122003334.13674.14424.stgit@zaytsev.su> (raw)
In-Reply-To: <20101122002747.13674.69384.stgit@zaytsev.su>
Signed-off-by: Alexey Zaytsev <alexey.zaytsev@gmail.com>
---
fs/notify/fsnotify.c | 24 ++++++++++++++----------
fs/notify/inode_mark.c | 2 +-
fs/notify/inotify/inotify_user.c | 2 +-
fs/notify/notification.c | 18 ++++++++++++++++--
include/linux/fsnotify_backend.h | 31 ++++++++++++++++++++++++++-----
5 files changed, 58 insertions(+), 19 deletions(-)
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 20dc218..7cabc1d 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -84,7 +84,8 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
}
/* Notify this dentry's parent about a child's events. */
-int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
+int __fsnotify_parent(struct path *path, struct dentry *dentry,
+ __u32 mask, struct fsnotify_range *range)
{
struct dentry *parent;
struct inode *p_inode;
@@ -108,10 +109,10 @@ int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
if (path)
ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
- dentry->d_name.name, 0);
+ dentry->d_name.name, 0, range);
else
ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
- dentry->d_name.name, 0);
+ dentry->d_name.name, 0, range);
}
dput(parent);
@@ -126,6 +127,7 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
__u32 mask, void *data,
int data_is, u32 cookie,
const unsigned char *file_name,
+ struct fsnotify_range *range,
struct fsnotify_event **event)
{
struct fsnotify_group *group = NULL;
@@ -167,10 +169,11 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x inode_mark=%p"
" inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x"
- " data=%p data_is=%d cookie=%d event=%p\n",
+ " data=%p data_is=%d cookie=%d range = {%lld, %lld}, event=%p\n",
__func__, group, to_tell, mnt, mask, inode_mark,
inode_test_mask, vfsmount_mark, vfsmount_test_mask, data,
- data_is, cookie, *event);
+ data_is, cookie, range ? range->start : -1,
+ range ? range->end : -1, *event);
if (!inode_test_mask && !vfsmount_test_mask)
return 0;
@@ -183,7 +186,7 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
if (!*event) {
*event = fsnotify_create_event(to_tell, mask, data,
data_is, file_name,
- cookie, GFP_KERNEL);
+ cookie, range, GFP_KERNEL);
if (!*event)
return -ENOMEM;
}
@@ -197,7 +200,8 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
* notification event in whatever means they feel necessary.
*/
int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
- const unsigned char *file_name, u32 cookie)
+ const unsigned char *file_name, u32 cookie,
+ struct fsnotify_range *range)
{
struct hlist_node *inode_node = NULL, *vfsmount_node = NULL;
struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL;
@@ -256,17 +260,17 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
if (inode_group > vfsmount_group) {
/* handle inode */
ret = send_to_group(to_tell, NULL, inode_mark, NULL, mask, data,
- data_is, cookie, file_name, &event);
+ data_is, cookie, file_name, range, &event);
/* we didn't use the vfsmount_mark */
vfsmount_group = NULL;
} else if (vfsmount_group > inode_group) {
ret = send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data,
- data_is, cookie, file_name, &event);
+ data_is, cookie, file_name, range, &event);
inode_group = NULL;
} else {
ret = send_to_group(to_tell, mnt, inode_mark, vfsmount_mark,
mask, data, data_is, cookie, file_name,
- &event);
+ range, &event);
}
if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index 4c29fcf..cd39df7 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -295,7 +295,7 @@ void fsnotify_unmount_inodes(struct list_head *list)
iput(need_iput_tmp);
/* for each watch, send FS_UNMOUNT and then remove it */
- fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
+ fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 0, NULL);
fsnotify_inode_delete(inode);
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 444c305..a5c2c69 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -524,7 +524,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
ignored_event = fsnotify_create_event(NULL, FS_IN_IGNORED, NULL,
FSNOTIFY_EVENT_NONE, NULL, 0,
- GFP_NOFS);
+ NULL, GFP_NOFS);
if (!ignored_event)
return;
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index f39260f..20b86a0 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -395,7 +395,8 @@ struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event)
*/
struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, void *data,
int data_type, const unsigned char *name,
- u32 cookie, gfp_t gfp)
+ u32 cookie, struct fsnotify_range *range,
+ gfp_t gfp)
{
struct fsnotify_event *event;
@@ -422,6 +423,19 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
event->to_tell = to_tell;
event->data_type = data_type;
+ /* The range might be allocated on stack. */
+ if (mask & FS_MODIFY) {
+ event->mod_range = *range;
+ } else {
+ event->mod_range.start = -1;
+ }
+
+ if (mask & FS_CLOSE_WRITE) {
+ event->cw_range = *range;
+ } else {
+ event->cw_range.start = -1;
+ }
+
switch (data_type) {
case FSNOTIFY_EVENT_PATH: {
struct path *path = data;
@@ -453,7 +467,7 @@ __init int fsnotify_notification_init(void)
fsnotify_event_holder_cachep = KMEM_CACHE(fsnotify_event_holder, SLAB_PANIC);
q_overflow_event = fsnotify_create_event(NULL, FS_Q_OVERFLOW, NULL,
- FSNOTIFY_EVENT_NONE, NULL, 0,
+ FSNOTIFY_EVENT_NONE, NULL, 0, NULL,
GFP_KERNEL);
if (!q_overflow_event)
panic("unable to allocate fsnotify q_overflow_event\n");
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 0a68f92..63237c5 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -240,6 +240,9 @@ struct fsnotify_event {
size_t name_len;
struct pid *tgid;
+ struct fsnotify_range mod_range; /* What has been modified last time */
+ struct fsnotify_range cw_range; /* What has been modified since the file was opened */
+
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
__u32 response; /* userspace answer to question */
#endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
@@ -305,8 +308,10 @@ struct fsnotify_mark {
/* main fsnotify call to send events */
extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
- const unsigned char *name, u32 cookie);
-extern int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask);
+ const unsigned char *name, u32 cookie,
+ struct fsnotify_range *range);
+extern int __fsnotify_parent(struct path *path, struct dentry *dentry,
+ __u32 mask, struct fsnotify_range *range);
extern void __fsnotify_inode_delete(struct inode *inode);
extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
extern u32 fsnotify_get_cookie(void);
@@ -420,22 +425,34 @@ extern void fsnotify_unmount_inodes(struct list_head *list);
extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
void *data, int data_is,
const unsigned char *name,
- u32 cookie, gfp_t gfp);
+ u32 cookie,
+ struct fsnotify_range *range,
+ gfp_t gfp);
/* fanotify likes to change events after they are on lists... */
extern struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event);
extern int fsnotify_replace_event(struct fsnotify_event_holder *old_holder,
struct fsnotify_event *new_event);
+static inline void fsnotify_update_range(struct fsnotify_range *new,
+ struct fsnotify_range *old)
+{
+ /* Cast because an empty range starts at -1. */
+ new->start = min((unsigned long long) old->start, (unsigned long long) new->start);
+ new->end = max(old->end, new->end);
+}
+
#else
static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
- const unsigned char *name, u32 cookie)
+ const unsigned char *name, u32 cookie,
+ struct fsnotify_range *range)
{
return 0;
}
-static inline int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
+static inline int __fsnotify_parent(struct path *path, struct dentry *dentry,
+ __u32 mask, struct fsnotify_range *range)
{
return 0;
}
@@ -460,6 +477,10 @@ static inline u32 fsnotify_get_cookie(void)
static inline void fsnotify_unmount_inodes(struct list_head *list)
{}
+static inline void fsnotify_update_range(struct fsnotify_range *new,
+ struct fsnotify_range *old)
+{}
+
#endif /* CONFIG_FSNOTIFY */
#endif /* __KERNEL __ */
next prev parent reply other threads:[~2010-11-22 0:32 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-22 0:31 [PATCH 0/4] Series short description Alexey Zaytsev
2010-11-22 0:33 ` [PATCH 1/4] fanotify: Shrink struct fanotify_event_metadata by 32 bits Alexey Zaytsev
2010-11-26 7:01 ` Alexey Zaytsev
2010-11-22 0:33 ` [PATCH 2/4] VFS: Tell fsnotify what part of the file might have changed Alexey Zaytsev
2010-11-22 0:33 ` Alexey Zaytsev [this message]
2010-11-22 0:37 ` [PATCH 4/4] fanotify: Expose the file changes to the user Alexey Zaytsev
2010-11-26 10:11 ` Tvrtko Ursulin
2010-11-26 11:21 ` Alexey Zaytsev
2010-11-26 11:41 ` Tvrtko Ursulin
2010-11-26 12:11 ` Alexey Zaytsev
2010-11-29 16:14 ` Eric Paris
2010-11-29 16:51 ` Alexey Zaytsev
2010-11-29 18:14 ` Eric Paris
2010-11-29 17:11 ` Tvrtko Ursulin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20101122003334.13674.14424.stgit@zaytsev.su \
--to=alexey.zaytsev@gmail.com \
--cc=agruen@linbit.com \
--cc=eparis@redhat.com \
--cc=hassan@dotfunk.com \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stefan@buettcher.org \
--cc=tvrtko.ursulin@sophos.com \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).