lkml.org 
[lkml]   [2010]   [Nov]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH 3/4] fsnotify: Handle the file change ranges
    From
    Date
    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 __ */


    \
     
     \ /
      Last update: 2010-11-22 01:35    [W:3.227 / U:1.152 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site