Author: asser Date: 2005-08-31 20:21:45 +0000 (Wed, 31 Aug 2005) New Revision: 42
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=linux-cifs-client&rev=42 Log: Added updating of CompletionFilter. A notify request will be reissued if the filter is updated. Modified: branches/SOC/linux-2.6bk-dnotify/fs/cifs/cifsfs.c branches/SOC/linux-2.6bk-dnotify/fs/cifs/fcntl.c branches/SOC/linux-2.6bk-dnotify/fs/cifs/misc.c Changeset: Modified: branches/SOC/linux-2.6bk-dnotify/fs/cifs/cifsfs.c =================================================================== --- branches/SOC/linux-2.6bk-dnotify/fs/cifs/cifsfs.c 2005-08-28 21:23:49 UTC (rev 41) +++ branches/SOC/linux-2.6bk-dnotify/fs/cifs/cifsfs.c 2005-08-31 20:21:45 UTC (rev 42) @@ -913,6 +913,8 @@ } kmem_cache_free(cifs_dnotify_cachep, dnotify_req); FreeXid(xid); + } else { + cFYI(1,("dnotify_req == NULL!")); } } } while(!signal_pending(current)); Modified: branches/SOC/linux-2.6bk-dnotify/fs/cifs/fcntl.c =================================================================== --- branches/SOC/linux-2.6bk-dnotify/fs/cifs/fcntl.c 2005-08-28 21:23:49 UTC (rev 41) +++ branches/SOC/linux-2.6bk-dnotify/fs/cifs/fcntl.c 2005-08-31 20:21:45 UTC (rev 42) @@ -72,9 +72,10 @@ struct cifsTconInfo *pTcon; char *full_path = NULL; __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES; + __u32 newfilter; __u16 netfid; - struct dir_notify_req *dnotify_req; - struct list_head *tmp, *tmp1; + struct dir_notify_req *dnotify_req, *tmpd; + struct list_head *tmp; xid = GetXid(); cifs_sb = CIFS_SB(file->f_dentry->d_sb); @@ -89,51 +90,93 @@ } else { cERROR(1,("cifs dir notify on file %s with arg 0x%lx (cifs arg 0x%lx)",full_path,arg,(unsigned long)convert_to_cifs_notify_flags(arg))); /* BB removeme BB */ + /* Find pending request if it exists */ + dnotify_req = NULL; + spin_lock(&GlobalMid_Lock); + list_for_each(tmp, &GlobalDnotifyReqList) { + tmpd = list_entry(tmp, struct dir_notify_req, lhead); + + if(tmpd->file == file) { + dnotify_req = tmpd; + break; + } + } + spin_unlock(&GlobalMid_Lock); + if(arg == 0) { - cFYI(1,("arg = 0, cancelling notification on %s",full_path)); - /* arg = 0 means cancel the notification */ - spin_lock(&GlobalMid_Lock); - list_for_each_safe(tmp, tmp1, &GlobalDnotifyReqList) { - dnotify_req = list_entry(tmp, struct dir_notify_req, lhead); + if(dnotify_req) { + cFYI(1,("arg = 0, cancelling notification on %s (netfid %d)",full_path,(int)netfid)); + /* arg = 0 means cancel the notification */ + rc = CIFSSMBCancel(xid, pTcon, dnotify_req->Uid, dnotify_req->Pid, + dnotify_req->PidHigh, dnotify_req->Tid, dnotify_req->Mid); - if(dnotify_req->file == file) { - rc = CIFSSMBCancel(xid, pTcon, dnotify_req->Uid, dnotify_req->Pid, - dnotify_req->PidHigh, dnotify_req->Tid, dnotify_req->Mid); + if(rc) { + cERROR(1,("Error in CIFSSMBCancel = %d", rc)); + } else { + rc = CIFSSMBClose(xid, pTcon, dnotify_req->netfid); - cFYI(1,("Error in CIFSSMBCancel = %d", rc)); if(rc) { - cFYI(1,("Error in CIFSSMBCancel = %d", rc)); + cERROR(1,("Error in CIFSSMBClose = %d", rc)); } } } - spin_unlock(&GlobalMid_Lock); } else { - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, - GENERIC_READ | SYNCHRONIZE, 0 /* create options */, - &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) { - cERROR(1,("Could not open directory for notify")); /* BB remove BB */ - } else { - filter = convert_to_cifs_notify_flags(arg); - if(filter != 0) { - rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid, - filter, cifs_sb->local_nls, file, arg & DN_MULTISHOT); + filter = convert_to_cifs_notify_flags(arg); + if(dnotify_req) { + newfilter = dnotify_req->filter | filter; + /* If CompletionFilter got added bits, re-request + * The kernel dnotify does this by doing + i_dnotify_mask |= new_mask */ + if((newfilter & filter) == filter && (newfilter & ~filter)) { + cFYI(1,("Updating filter on %s (netfid %d)",full_path,(int)netfid)); + rc = CIFSSMBCancel(xid, pTcon, dnotify_req->Uid, dnotify_req->Pid, + dnotify_req->PidHigh, dnotify_req->Tid, dnotify_req->Mid); + + if(rc) { + cERROR(1,("Error in CIFSSMBCancel: %d", rc)); + } else { + rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid, + filter, cifs_sb->local_nls, file, arg & DN_MULTISHOT); + + if(rc) { + cERROR(1,("Error in CIFSSMBNotify: %d", rc)); + } + } } else { - /* ASF TODO: Close the file handle */ - rc = -EINVAL; + cERROR(1,("Filter didn't change, doing nothing (old:0x%lx new:0x%lx)",filter,newfilter)); } - /* 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 */ - cERROR(1,("notify rc %d",rc)); + } else { + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, + GENERIC_READ | SYNCHRONIZE, 0 /* create options */, + &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) { + cERROR(1,("Could not open directory for notify")); /* BB remove BB */ + } else { + if(filter != 0) { + rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid, + filter, cifs_sb->local_nls, file, arg & DN_MULTISHOT); + + } else { + rc = CIFSSMBClose(xid, pTcon, netfid); + if(rc) { + cERROR(1,("Could not close open directory (netfid %d) rc = %d", netfid, rc)); + } + 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 */ + cERROR(1,("notify rc %d",rc)); + } } } } FreeXid(xid); + cERROR(1,("notify rc %d",rc)); return rc; } Modified: branches/SOC/linux-2.6bk-dnotify/fs/cifs/misc.c =================================================================== --- branches/SOC/linux-2.6bk-dnotify/fs/cifs/misc.c 2005-08-28 21:23:49 UTC (rev 41) +++ branches/SOC/linux-2.6bk-dnotify/fs/cifs/misc.c 2005-08-31 20:21:45 UTC (rev 42) @@ -406,9 +406,9 @@ __u32 data_offset = 0; cFYI(1,("pSMBr ByteCount:%ld TotalParameterCount:%ld ParameterCount:%ld DataCount:%ld", (unsigned long)pSMBr->ByteCount, (unsigned long)pSMBr->TotalParameterCount, (unsigned long)pSMBr->ParameterCount, (unsigned long)pSMBr->DataCount)); cFYI(1,("pSMBr ParameterOffset:%ld DataOffset:%ld", (unsigned long)pSMBr->ParameterOffset, (unsigned long)pSMBr->DataOffset)); - pnotify = (struct file_notify_information *) (&pSMBr->hdr.Protocol) + pSMBr->DataOffset; - cFYI(1,("pnotify NextEntryOffset:%lx Action:%lx FileNameLength:%ld",(unsigned long)pnotify->NextEntryOffset,(unsigned long)pnotify->Action,(unsigned long)pnotify->FileNameLength)); - cFYI(1,("notify err 0x%x",pSMBr->hdr.Status.CifsError)); + //pnotify = (struct file_notify_information *) (&pSMBr->hdr.Protocol) + pSMBr->DataOffset; + //cFYI(1,("pnotify NextEntryOffset:%lx Action:%lx FileNameLength:%ld",(unsigned long)pnotify->NextEntryOffset,(unsigned long)pnotify->Action,(unsigned long)pnotify->FileNameLength)); + //cFYI(1,("notify err 0x%x",pSMBr->hdr.Status.CifsError)); /* Find the request on the req list */ spin_lock(&GlobalMid_Lock); list_for_each_safe(tmp, tmp1, &GlobalDnotifyReqList) { @@ -418,13 +418,15 @@ dnotify_req->PidHigh == pSMBr->hdr.PidHigh && dnotify_req->Pid == pSMBr->hdr.Pid) { - list_del(tmp); + cFYI(1,("Found pending request with mid:%ld pidhigh:%d pid:%d",dnotify_req->Mid,dnotify_req->PidHigh,dnotify_req->Pid)); + list_del(&dnotify_req->lhead); if ((NT_STATUS_CANCELLED) == le32_to_cpu(pSMBr->hdr.Status.CifsError)) { cFYI(1,("Request was cancelled (err %lx)", pSMBr->hdr.Status.CifsError)); - kfree(dnotify_req); + kmem_cache_free(cifs_dnotify_cachep, dnotify_req); } else if(SUCCESS == le32_to_cpu(pSMBr->hdr.Status.CifsError) || STATUS_NOTIFY_ENUM_DIR == le32_to_cpu(pSMBr->hdr.Status.CifsError)) { + cFYI(1,("success response (status %lx)", pSMBr->hdr.Status.CifsError)); list_add_tail(&dnotify_req->lhead, &GlobalDnotifyRsp_Q); } else { cFYI(1,("Unknown NOTIFY response 0x%lx", pSMBr->hdr.Status.CifsError));
