public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Yi Yang <yang.y.yi@gmail.com>
To: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Cc: LKML <linux-kernel@vger.kernel.org>,
	Andrew Morton <akpm@osdl.org>, Matt Helsley <matthltc@us.ibm.com>
Subject: Re: [2.6.16 PATCH] Filesystem Events Connector v4
Date: Tue, 28 Mar 2006 21:30:03 +0800	[thread overview]
Message-ID: <44293A5B.3090604@gmail.com> (raw)
In-Reply-To: <20060328075126.GA11334@2ka.mipt.ru>

Evgeniy Polyakov 写道:
> On Mon, Mar 27, 2006 at 11:05:38PM +0800, Yi Yang (yang.y.yi@gmail.com) wrote:
>   
>> This release is v4, compared with v3, it adds and improve some functions:
>> 	* The user can set event filter in order to just get 
>> 	  those events who concerns, filter may be based on 
>> 	  event mask, pid, uid and gid.
>> 	* it removes the atomic_t variable cn_fs_listener and
>> 	  adopt a smart way to decide whether it should send a
>> 	  event.
>> 	* Add several filter operation commands and acknowleges
>> 	  , add a new struct fsevent_filter as command struct.
>>
>> basically, these functions enable it to meet the user's requirements better,
>>  but, it can't do better because of connector broadcast property, I plan to
>>  use netlink to let different user see different events, filter is based on
>>  userspace appplication using it, every application can set its own filters
>>  and see different events.
>>
>>  drivers/connector/Kconfig     |   12 +
>>  drivers/connector/Makefile    |    1 
>>  drivers/connector/cn_fs.c     |  298 +++++++++++++++++++++++++++++++++++++++++
>>  drivers/connector/connector.c |    4 
>>  fs/namespace.c                |   12 +
>>  include/linux/connector.h     |    8 -
>>  include/linux/fsevent.h       |  122 +++++++++++++++++
>>  include/linux/fsnotify.h      |   37 +++++
>>  8 files changed, 490 insertions(+), 4 deletions(-)
>>
>> Signed-off-by: Yi Yang <yang.y.yi@gmail.com>
>>     
>
>   
>> +
>> +#ifdef CONFIG_FS_EVENTS
>> +	{
>> +	u32 fsevent_mask = 0;
>> +	if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE))
>> +		fsevent_mask |= FSEVENT_MODIFY_ATTRIB;
>> +	if ((ia_valid & ATTR_ATIME) && (ia_valid & ATTR_MTIME))
>> +		fsevent_mask |= FSEVENT_MODIFY_ATTRIB;
>> +	else if (ia_valid & ATTR_ATIME)
>> +		fsevent_mask |= FSEVENT_ACCESS;
>> +	else if (ia_valid & ATTR_MTIME)
>> +		fsevent_mask |= FSEVENT_MODIFY;
>> +	if (ia_valid & ATTR_SIZE)
>> +		fsevent_mask |= FSEVENT_MODIFY;
>> +	if (fsevent_mask)
>> +		raise_fsevent(dentry, fsevent_mask);
>> +	}
>> +#endif /* CONFIG_FS_EVENTS */
>>  }
>>     
>
> Coding style?
>
>
>   
>> --- a/drivers/connector/connector.c.orig	2006-03-27 21:35:15.000000000 +0800
>> +++ b/drivers/connector/connector.c	2006-03-27 21:35:53.000000000 +0800
>> @@ -111,9 +111,7 @@ int cn_netlink_send(struct cn_msg *msg, 
>>  
>>  	NETLINK_CB(skb).dst_group = group;
>>  
>> -	netlink_broadcast(dev->nls, skb, 0, group, gfp_mask);
>> -
>> -	return 0;
>> +	return (netlink_broadcast(dev->nls, skb, 0, group, gfp_mask));
>>  
>>  nlmsg_failure:
>>  	kfree_skb(skb);
>>     
>
> This error value is propageted back in current connector code already.
>   
Which version of kernel do you mean? for 2.6.16, it doesn't return 
netlink_broadcast's return value.
>   
>> +
>> +	/* The following definitions are commands for event filter
>> +	 * , in acknowlege event for the corresponding command, it
>> +	 * will set to type field of struct fsevent.
>> +	*/
>>     
>
> Not an eye-candy.
>
>   
>> +	FSEVENT_FILTER_ALL = 	0x08000000,	/* For all events */
>> +	FSEVENT_FILTER_PID = 	0x10000000,	/* For some process ID */
>> +	FSEVENT_FILTER_UID = 	0x20000000,	/* For some user ID */
>> +	FSEVENT_FILTER_GID =	0x40000000,	/* For some group ID */
>> +
>> +	FSEVENT_ISDIR = 	0x80000000	/* It is set for a dir */
>> +};
>> +
>> +#define FSEVENT_MASK 0x800003ff
>> +
>> +typedef unsigned long fsevent_mask_t;
>> +
>> +struct fsevent_filter {
>> +	/* filter type, it just is one or bit-or of them
>> +	 * FSEVENT_FILTER_ALL
>> +	 * FSEVENT_FILTER_PID
>> +	 * FSEVENT_FILTER_UID
>> +	 * FSEVENT_FILTER_GID
>> +	 */
>> +	enum fsevent_type type;	/* filter type */
>> +
>> +	/* mask of file system events the user listen or ignore
>> +	 * if the user need to ignore all the events of some pid
>> +	 * , gid or uid, he(she) must set mask to FSEVENT_MASK.
>> +	 */ 
>>     
>
> "," on the new line.
>
>   
>> +static void turn_off_fsevents(void)
>> +{
>> +	write_lock(&fsevents_lock);
>> +	fsevents_mask = 0;
>> +	fsevents_pid_mask = 0;
>> +	filter_pid = -1;
>> +	fsevents_uid_mask = 0;
>> +	filter_uid = -1;
>> +	fsevents_gid_mask = 0;
>> +	filter_gid = -1;
>> +	write_unlock(&fsevents_lock);
>> +}
>> +
>> +static int filter_fsevents(u32 * mask)
>> +{
>> +	int ret = 0;
>> +
>> +	(*mask) &= FSEVENT_MASK;
>> +	read_lock(&fsevents_lock);
>>     
>
> You do want to use RCU locking here.
> It is fast path and it is not allowed to get global
> smp-unfriendly read lock.
>
>   
You are very right, I'll convert to RCU lock.
>> +	if (current->pid == filter_pid) {
>> +		(*mask) &= fsevents_pid_mask;
>> +		if ((*mask) == 0) {
>> +			ret = -2;
>> +		}
>> +		goto release_lock;
>> +	}
>> +			
>> +	if (current->uid == filter_uid) {
>> +		(*mask) &= fsevents_uid_mask;
>> +		if ((*mask) == 0) {
>> +			ret = -3;
>> +		}
>> +		goto release_lock;
>> +	}
>> +		
>> +	if (current->gid == filter_gid) {
>> +		(*mask) &= fsevents_gid_mask;
>> +		if ((*mask) == 0) {
>> +			ret = -4;
>> +		}
>> +		goto release_lock;
>> +	}
>> +
>> +	if ((((*mask) & FSEVENT_ISDIR) == FSEVENT_ISDIR)
>> +		 & ((fsevents_mask & FSEVENT_ISDIR) == 0)) {
>> +		ret = -1;
>> +		goto release_lock;
>> +	}
>> +
>> +	(*mask) &= fsevents_mask;
>> +	if ((*mask) == 0) {
>> +		ret = -5;
>> +	}
>> +
>> +release_lock:
>> +	read_unlock(&fsevents_lock);
>> +	return ret;
>> +}
>>     
>
> Can it be somehow turned off or moved into per-cpu variables?
> It is a lot of smp-unfriendly access of global variables.
>
> It of course costs much less than allocations and copies,
> but no global lock at least.
>   
I'll plan to just move them to specific process so that they are only 
for this process, so
lock can be removed completely.
>   
>> +	if (newname) {
>> +		event->new_fname_len = strlen(newname);
>> +		 append_string(&nameptr, newname, event->new_fname_len);
>> +		event->len += event->new_fname_len + 1;
>> +	}
>>     
>
> A space from nowhere.
>
>   
>> +	if (ret == -ESRCH) {
>> +		turn_off_fsevents();
>> +	}
>>     
>
> Coding style.
>
>   
>> +void raise_fsevent(struct dentry * dentryp, u32 mask)
>> +{
>> +	if (dentryp->d_inode && (MAJOR(dentryp->d_inode->i_rdev) == 4))
>> +		return;
>> +	__raise_fsevent(dentryp->d_name.name, NULL, mask);
>> +}
>>     
>
> Yep, tty can mess the things.
> Maybe remove all special devices at all?
>
>   
>> +EXPORT_SYMBOL_GPL(raise_fsevent);
>> +
>> +void raise_fsevent_create(struct inode * inode, const char * name, u32 mask)
>> +{
>> +	read_lock(&fsevents_lock);
>> +	__raise_fsevent(name, NULL, mask);
>> +}
>>     
>
> Lost read_lock here - you will grab it in
> __raise_fsevent()->filter_fsevents().
>
>
>   
>> +static int __init cn_fs_init(void)
>> +{
>> +	int err;
>> +
>> +	if ((err = cn_add_callback(&cn_fs_event_id, "cn_fs",
>> +	 			   &cn_fsevent_filter_ctl))) {
>> +		printk(KERN_WARNING "cn_fs failed to register\n");
>> +		return err;
>> +	}
>> +	return 0;
>> +}
>> +
>> +module_init(cn_fs_init);
>>     
>
> Add module_exit() too.
>
> Main issue is locking in this patchset - it is not allowed to have such
> a global lock in those pathes, moving this to RCU is the way to go and definitely not a
> problem to implement.
>
> Thank you.
>   
Thank for your careful review very much, I'll commit a new version to 
fix your concerns, thanks again.


  reply	other threads:[~2006-03-28 13:29 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-03-27 15:05 [2.6.16 PATCH] Filesystem Events Connector v4 Yi Yang
2006-03-28  7:51 ` Evgeniy Polyakov
2006-03-28 13:30   ` Yi Yang [this message]
2006-03-28 12:35     ` Evgeniy Polyakov

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=44293A5B.3090604@gmail.com \
    --to=yang.y.yi@gmail.com \
    --cc=akpm@osdl.org \
    --cc=johnpol@2ka.mipt.ru \
    --cc=linux-kernel@vger.kernel.org \
    --cc=matthltc@us.ibm.com \
    /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