URN Logo
UNIX Resources » Linux » China Linux Forum » Linux内核技术 » 第19页 » 重读2.4 --027 fs/attr.c dnotify.c
announcement 声明: 本页内容为中国Linux论坛的内容镜像,文章的版权以及其他所有的相关权利属于中国Linux论坛和相应文章的作者,如果转载,请注明文章来源及相关版权信息。
Resources
China Linux Forum(finished)
Linux Forum(finished)
FreeBSD China(finished)
linuxforum.com
  LinuxForum General Chat
  Linux Advocacy
  LinuxForum Polls
  Introductions
  Linux Kernel Support
  Patch Management
  Development Release
  Linux Programming
  Linux Security
  Linux Software
  Linux Hardware Problems
    Linux Video Problems
    Linux Sound Problems
  Linux Networking Support
  Linux Printing Support
  Linux Human Interface Devices Support
  Linux Data Storage Support
  Linux Applications Support
  Linux Installation Support
  Linux Laptops Support
  Linux Motherboard, Chipsets, CPU, Memory
  Miscellaneous
  Debian Linux Support
  Ubuntu Linux Support
  LiveCD Discussions
  Gentoo Linux Support
  Mandrake Linux Support
  Redhat / Fedora Linux Support
  Slackware Linux Support
  SuSE Linux Support
  CentOS Linux Support
  Linux Web Servers
  Linux DNS Servers
  Linux Database Servers
  Linux Email Servers
  Linux FTP Servers
  Linux Squid Proxy Server
  Linux Samba Help
  Linux cPanel Help
  Linux Ensim Help
  Linux Plesk Help
  Linux Webmin / Usermin Help
  Qmail Toaster Help
  Linux Games
  Windows Game Emulation
  Linux Discussions
  General Linux Discussions
  Red Hat Linux Discussions
  More Red Hat Linux Discussions
  Mandrake Linux Discussions
  Slackware Linux Discussions
  SuSE Linux Discussions
  Debian Discussions
  Samba Help
  Linux Security
  Linux Networking
  Gentoo Help
  Operating System Rant Forum
  Hardware Rants
   
重读2.4 --027 fs/attr.c dnotify.c
重读2.4 --027 fs/attr.c dnotify.c - hyl [2007-11-13 20:56 | 11,415 byte(s)]
 
Re: 重读2.4 --027 fs/attr.c dnotify.c - zyzii [2007-11-13 21:31 | 199 byte(s)]
 
Subject: 重读2.4 --027 fs/attr.c dnotify.c
Author: hyl    Posted: 2007-11-13 20:56    Length: 11,415 byte(s)
[Original] [Print] [Top]


attr.c
2007-3-6


inode,即文件,拥有各种属性,时间/从属/size等。内核提供对这些属性改变的通知事件。同一?
鑫募梢杂泻芏嗟慕套⒉崃薾otify
每个进程感兴趣的属性也可以不同。这个文件提供了几个接口,来统一对文件属性的修改进行鉴权
/实施/以及通知。
struct iattr *attr : 要修改的属性通过这个结构传递,fs.h 定义的
#define ATTR_MODE 1
#define ATTR_UID 2
设置到iattr的ia_valid,来指明要修改的属性,之后的鉴权/修改/通知都通过ia_valid来确定。
相关的代码并不复杂。简单罗列到这里
以供参考。



int inode_change_ok(struct inode *inode, struct iattr *attr)
{
int retval = -EPERM;
unsigned int ia_valid = attr->ia_valid;


if (ia_valid & ATTR_FORCE)
goto fine;


if ((ia_valid & ATTR_UID) &&
(current->fsuid != inode->i_uid ||
attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
goto error;


if ((ia_valid & ATTR_GID) &&
(!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)
&&
!capable(CAP_CHOWN))
goto error;


if (ia_valid & ATTR_MODE) {
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
goto error;

if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
inode->i_gid) && !capable(CAP_FSETID))
attr->ia_mode &= ~S_ISGID;
}


if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
goto error;
}
fine:
retval = 0;
error:
return retval;
}


void inode_setattr(struct inode * inode, struct iattr * attr)
{
unsigned int ia_valid = attr->ia_valid;

if (ia_valid & ATTR_UID)
inode->i_uid = attr->ia_uid;
if (ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (ia_valid & ATTR_SIZE)
vmtruncate(inode, attr->ia_size);
if (ia_valid & ATTR_ATIME)
inode->i_atime = attr->ia_atime;
if (ia_valid & ATTR_MTIME)
inode->i_mtime = attr->ia_mtime;
if (ia_valid & ATTR_CTIME)
inode->i_ctime = attr->ia_ctime;
if (ia_valid & ATTR_MODE) {
inode->i_mode = attr->ia_mode;
if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
inode->i_mode &= ~S_ISGID;
}
mark_inode_dirty(inode);
}


static int setattr_mask(unsigned int ia_valid)
{
unsigned long dn_mask = 0;

if (ia_valid & ATTR_UID)
dn_mask |= DN_ATTRIB;
if (ia_valid & ATTR_GID)
dn_mask |= DN_ATTRIB;
if (ia_valid & ATTR_SIZE)
dn_mask |= DN_MODIFY;

if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME))
dn_mask |= DN_ATTRIB;
else if (ia_valid & ATTR_ATIME)
dn_mask |= DN_ACCESS;
else if (ia_valid & ATTR_MTIME)
dn_mask |= DN_MODIFY;
if (ia_valid & ATTR_MODE)
dn_mask |= DN_ATTRIB;
return dn_mask;
}


int notify_change(struct dentry * dentry, struct iattr * attr)
{
struct inode *inode = dentry->d_inode;
int error;
time_t now = CURRENT_TIME;
unsigned int ia_valid = attr->ia_valid;

if (!inode)
BUG();

attr->ia_ctime = now;
if (!(ia_valid & ATTR_ATIME_SET))
attr->ia_atime = now;
if (!(ia_valid & ATTR_MTIME_SET))
attr->ia_mtime = now;

lock_kernel();
if (inode->i_op && inode->i_op->setattr)

error = inode->i_op->setattr(dentry, attr);
else {

error = inode_change_ok(inode, attr);
if (!error)
inode_setattr(inode, attr);
}
unlock_kernel();
if (!error) {
unsigned long dn_mask = setattr_mask(ia_valid);
if (dn_mask)
inode_dir_notify(dentry->d_parent->d_inode, dn_mask);
}
return error;
}

 

 

dnotify.c
2007.3.6


这个文件和此话题密切相关,顺便也解决了吧。想要监控一个文件的时候,需要首先打开这个文件
,然后通过fcntl注册,就会通过信号
接受到这个文件相关属性的通知消息。
为此,struct
file中有一个f_owner,其中记录了打开这个文件的进程,此文件的等信息。fcntl的时候就需要设
置好这个结构,notify
就是据此找到信号应该发给那个进程。


另外,需要在inode上挂一个dnotify_struct的链表,记录所有需要得到通知的file(pid记录于fi
le-〉f_owner).此文件就是提供管理
这些信息的函数。

+------+
|dentry|
+-/----+
|
| +-------------+ +-------------+
--------|dentry_notify|--|dentry_notify|
+------/------+ +-------------+
|
|
|
+------------------+
| file->f_owner.pid |
+-------------------+
实在没有什么说的,见上图和这个两个简单的函数。



int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
{
struct dnotify_struct *dn = NULL;
struct dnotify_struct *odn;
struct dnotify_struct **prev;
struct inode *inode;
int turning_off = (arg & ~DN_MULTISHOT) == 0;

if (!turning_off && !dir_notify_enable)
return -EINVAL;
inode = filp->f_dentry->d_inode;
if (!S_ISDIR(inode->i_mode))
return -ENOTDIR;
if (!turning_off) {
dn = kmem_cache_alloc(dn_cache, SLAB_KERNEL);
if (dn == NULL)
return -ENOMEM;
}
write_lock(&dn_lock);
prev = &inode->i_dnotify;
for (odn = *prev; odn != NULL; prev = &odn->dn_next, odn = *prev)
if (odn->dn_filp == filp)
break;
if (odn != NULL) {
if (turning_off) {
*prev = odn->dn_next;
redo_inode_mask(inode);
dn = odn;
goto out_free;
}
odn->dn_fd = fd;
odn->dn_mask |= arg;
inode->i_dnotify_mask |= arg & ~DN_MULTISHOT;
goto out_free;
}
if (turning_off)
goto out;
filp->f_owner.pid = current->pid;
filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid;
dn->dn_magic = DNOTIFY_MAGIC;
dn->dn_mask = arg;
dn->dn_fd = fd;
dn->dn_filp = filp;
inode->i_dnotify_mask |= arg & ~DN_MULTISHOT;
dn->dn_next = inode->i_dnotify;
inode->i_dnotify = dn;
out:
write_unlock(&dn_lock);
return 0;
out_free:
kmem_cache_free(dn_cache, dn);
goto out;
}


void __inode_dir_notify(struct inode *inode, unsigned long event)
{
struct dnotify_struct * dn;
struct dnotify_struct **prev;
struct fown_struct * fown;
int changed = 0;

write_lock(&dn_lock);
prev = &inode->i_dnotify;
while ((dn = *prev) != NULL) {
if (dn->dn_magic != DNOTIFY_MAGIC) {
printk(KERN_ERR "__inode_dir_notify: bad magic "
"number in dnotify_struct! ");
goto out;
}
if ((dn->dn_mask & event) == 0) {
prev = &dn->dn_next;
continue;
}
fown = &dn->dn_filp->f_owner;
if (fown->pid)
send_sigio(fown, dn->dn_fd, POLL_MSG);
if (dn->dn_mask & DN_MULTISHOT)
prev = &dn->dn_next;
else {
*prev = dn->dn_next;
changed = 1;
kmem_cache_free(dn_cache, dn);
}
}
if (changed)
redo_inode_mask(inode);
out:
write_unlock(&dn_lock);
}

 
[Original] [Print] [Top]
Subject: Re: 重读2.4 --027 fs/attr.c dnotify.c
Author: zyzii    Posted: 2007-11-13 21:31    Length: 199 byte(s)
[Original] [Print] [Top]
版调的不好了啊,参考:
http://www.linuxforum.net/forum/faq_chinese.php?Cat=
----
应用程序是LINUX的软肋。
[Original] [Print] [Top]
« Previous thread
重读2.4 --028 fs/bad_inode.c
Linux内核技术
19
Next thread »
重读2.4--026 pre /fs
     

Copyright © 2018 UNIX Resources Network, All Rights Reserved.    About URN | Privacy & Legal | Help | Contact us