X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fcifs%2Ffcntl.c;h=633a938113287f2d0a75c6ba58953e800b755747;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=b908768b62159c922f2711dba82b651b19afc7ad;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c index b908768b6..633a93811 100644 --- a/fs/cifs/fcntl.c +++ b/fs/cifs/fcntl.c @@ -27,6 +27,45 @@ #include "cifsproto.h" #include "cifs_unicode.h" #include "cifs_debug.h" +#include "cifsfs.h" + +static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags) +{ + __u32 cifs_ntfy_flags = 0; + + /* No way on Linux VFS to ask to monitor xattr + changes (and no stream support either */ + if(fcntl_notify_flags & DN_ACCESS) { + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS; + } + if(fcntl_notify_flags & DN_MODIFY) { + /* What does this mean on directories? */ + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_SIZE; + } + if(fcntl_notify_flags & DN_CREATE) { + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION | + FILE_NOTIFY_CHANGE_LAST_WRITE; + } + if(fcntl_notify_flags & DN_DELETE) { + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE; + } + if(fcntl_notify_flags & DN_RENAME) { + /* BB review this - checking various server behaviors */ + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_FILE_NAME; + } + if(fcntl_notify_flags & DN_ATTRIB) { + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY | + FILE_NOTIFY_CHANGE_ATTRIBUTES; + } +/* if(fcntl_notify_flags & DN_MULTISHOT) { + cifs_ntfy_flags |= ; + } */ /* BB fixme - not sure how to handle this with CIFS yet */ + + + return cifs_ntfy_flags; +} int cifs_dir_notify(struct file * file, unsigned long arg) { @@ -37,33 +76,44 @@ int cifs_dir_notify(struct file * file, unsigned long arg) struct cifsTconInfo *pTcon; char *full_path = NULL; __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES; - __u16 netfid; + __u16 netfid; + + + if(experimEnabled == 0) + return 0; xid = GetXid(); cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; - down(&file->f_dentry->d_sb->s_vfs_rename_sem); full_path = build_path_from_dentry(file->f_dentry); - up(&file->f_dentry->d_sb->s_vfs_rename_sem); if(full_path == NULL) { rc = -ENOMEM; } else { - cFYI(1,("cifs dir notify on file %s",full_path)); + cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ | SYNCHRONIZE, 0 /* create options */, - &netfid, &oplock,NULL, cifs_sb->local_nls); + &netfid, &oplock,NULL, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); /* BB fixme - add this handle to a notify handle list */ if(rc) { - cFYI(1,("Could not open directory for notify")); + cERROR(1,("Could not open directory for notify")); /* BB remove BB */ } else { - rc = CIFSSMBNotify(xid, pTcon, 1 /* subdirs */, netfid, - filter, cifs_sb->local_nls); + filter = convert_to_cifs_notify_flags(arg); + if(filter != 0) { + rc = CIFSSMBNotify(xid, pTcon, + 0 /* no subdirs */, netfid, + filter, file, arg & DN_MULTISHOT, + cifs_sb->local_nls); + } else { + rc = -EINVAL; + } /* BB add code to close file eventually (at unmount it would close automatically but may be a way to do it easily when inode freed or when notify info is cleared/changed */ + cFYI(1,("notify rc %d",rc)); } }