From patchwork Mon Feb 23 20:47:59 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve French X-Patchwork-Id: 8509 Received: from lists.samba.org (mail.samba.org [66.70.73.150]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n1NKmO8I003686 for ; Mon, 23 Feb 2009 20:48:24 GMT Received: from dp.samba.org (localhost [127.0.0.1]) by lists.samba.org (Postfix) with ESMTP id 78EE9163C1E for ; Mon, 23 Feb 2009 20:48:10 +0000 (GMT) X-Spam-Checker-Version: SpamAssassin 3.1.7 (2006-10-05) on dp.samba.org X-Spam-Level: X-Spam-Status: No, score=-3.1 required=3.8 tests=AWL,BAYES_00, DNS_FROM_RFC_POST,SPF_PASS autolearn=no version=3.1.7 X-Original-To: linux-cifs-client@lists.samba.org Delivered-To: linux-cifs-client@lists.samba.org Received: from yw-out-1718.google.com (yw-out-1718.google.com [74.125.46.155]) by lists.samba.org (Postfix) with ESMTP id 7CA6A1639B0 for ; Mon, 23 Feb 2009 20:47:46 +0000 (GMT) Received: by yw-out-1718.google.com with SMTP id 9so819490ywk.80 for ; Mon, 23 Feb 2009 12:47:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:date:message-id:subject :from:to:content-type; bh=aEfiZ0J5+mDXDrhA8bmiHTzCtjKIK712jatLB/Cr6oQ=; b=xraNmuNBd0wfurS/cNpv/hNAJUTZ+Agq/y+P9naC+gLZFqjP8HK9XJM62Ez2EydvCk 75MgCGimEdEd66v4HukfvfeCuFscBdJ4f7CJGEQTr3pyzQU6e5B7CSxzFTYiv+bxWqwx yYAGPUN37vcPPCEtjcPFyxoLx1qrpbK/80qYQ= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=NGrJ55Vpx32phn4iblrlhcf2JOnUTdQjdK7T4lVAJYnsTHWEFSUT8TCvflFDf3fl/n +YGCZXUrOC8PgoNeyZJJyG0sV6vSo7mC5HufUteYWRoIyTQ8BPLbiwswg4fDOe508NmL iH8FvaXq3NVRjYbmKEZWQWx+aX06xKkhjABpI= MIME-Version: 1.0 Received: by 10.231.10.140 with SMTP id p12mr6613553ibp.50.1235422079205; Mon, 23 Feb 2009 12:47:59 -0800 (PST) Date: Mon, 23 Feb 2009 14:47:59 -0600 Message-ID: <524f69650902231247t3602e4day73fc7a23afd6aec7@mail.gmail.com> From: Steve French To: "linux-cifs-client@lists.samba.org" , linux-fsdevel Subject: [linux-cifs-client] [PATCH] [CIFS] use newer posix open SMB in cifs_reopen_file X-BeenThere: linux-cifs-client@lists.samba.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: The Linux CIFS VFS client List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-cifs-client-bounces+patchwork-cifs-client=patchwork.kernel.org@lists.samba.org Errors-To: linux-cifs-client-bounces+patchwork-cifs-client=patchwork.kernel.org@lists.samba.org Still working on a patch to cifs_open (to use the newer posix open protocol operation when available, e.g. when server is Samba) I didn't see a way to avoid the warnings on the fmode_t casts (to and from int) caused by the different definitions of the O MODE bits in the fs headers in the include directory. diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 596fc86..a069e7b 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -92,6 +92,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec); extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); +extern int cifs_posix_open(char *full_path, struct inode **pinode, + struct super_block *sb, int mode, int oflags, + int *poplock, __u16 *pnetfid, int xid); extern void posix_fill_in_inode(struct inode *tmp_inode, FILE_UNIX_BASIC_INFO *pData, int isNewInode); extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 89fb728..f9b6f68 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -129,7 +129,7 @@ cifs_bp_rename_retry: return full_path; } -static int cifs_posix_open(char *full_path, struct inode **pinode, +int cifs_posix_open(char *full_path, struct inode **pinode, struct super_block *sb, int mode, int oflags, int *poplock, __u16 *pnetfid, int xid) { @@ -187,7 +187,9 @@ static int cifs_posix_open(char *full_path, struct inode **pinode, if (!pinode) goto posix_open_ret; /* caller does not need info */ - *pinode = cifs_new_inode(sb, &presp_data->UniqueId); + if (*pinode == NULL) + *pinode = cifs_new_inode(sb, &presp_data->UniqueId); + /* else an inode was passed in. Update its info, don't create one */ /* We do not need to close the file if new_inode fails since the caller will retry qpathinfo as long as inode is null */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 83b4741..770e2ee 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -78,8 +78,36 @@ static inline int cifs_convert_flags(unsigned int flags) return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA); +} +static inline fmode_t cifs_posix_convert_flags(unsigned int flags) +{ + fmode_t posix_flags = 0; + if ((flags & O_ACCMODE) == O_RDONLY) + posix_flags = FMODE_READ; + else if ((flags & O_ACCMODE) == O_WRONLY) + posix_flags = FMODE_WRITE; + else if ((flags & O_ACCMODE) == O_RDWR) { + /* GENERIC_ALL is too much permission to request + can cause unnecessary access denied on create */ + /* return GENERIC_ALL; */ + posix_flags = FMODE_READ | FMODE_WRITE; + } + /* can not map O_CREAT or O_EXCL or O_TRUNC flags when + reopening a file. They had their effect on the original open */ + if (flags & O_APPEND) + posix_flags |= (fmode_t)O_APPEND; + if (flags & O_SYNC) + posix_flags |= (fmode_t)O_SYNC; + if (flags & O_DIRECTORY) + posix_flags |= (fmode_t)O_DIRECTORY; + if (flags & O_NOFOLLOW) + posix_flags |= (fmode_t)O_NOFOLLOW; + if (flags & O_DIRECT) + posix_flags |= (fmode_t)O_DIRECT; + + return posix_flags; } static inline int cifs_get_disposition(unsigned int flags) @@ -349,7 +377,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) int rc = -EACCES; int xid, oplock; struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; + struct cifsTconInfo *tcon; struct cifsFileInfo *pCifsFile; struct cifsInodeInfo *pCifsInode; struct inode *inode; @@ -387,7 +415,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) } cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb->tcon; + tcon = cifs_sb->tcon; /* can not grab rename sem here because various ops, including those that already have the rename sem can end up causing writepage @@ -404,20 +432,37 @@ reopen_error_exit: cFYI(1, ("inode = 0x%p file flags 0x%x for %s", inode, file->f_flags, full_path)); - desiredAccess = cifs_convert_flags(file->f_flags); if (oplockEnabled) oplock = REQ_OPLOCK; else oplock = 0; + if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_POSIX_PATH_OPS_CAP & + le64_to_cpu(tcon->fsUnixInfo.Capability))) { + int oflags = (int) cifs_posix_convert_flags(file->f_flags); + /* can not refresh inode info since size could be stale */ + rc = cifs_posix_open(full_path, NULL, inode->i_sb, + cifs_sb->mnt_file_mode /* ignored */, + oflags, &oplock, &netfid, xid); + if (rc == 0) { + cFYI(1, ("posix reopen succeeded")); + goto reopen_success; + } + /* fallthrough to retry open the old way on errors, especially + in the reconnect path it is important to retry hard */ + } + + desiredAccess = cifs_convert_flags(file->f_flags); + /* Can not refresh inode by passing in file_info buf to be returned by SMBOpen and then calling get_inode_info with returned buf since file might have write behind data that needs to be flushed and server version of file size can be stale. If we knew for sure that inode was not dirty locally we could do this */ - rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, + rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -426,6 +471,7 @@ reopen_error_exit: cFYI(1, ("cifs_open returned 0x%x", rc)); cFYI(1, ("oplock: %d", oplock)); } else { +reopen_success: pCifsFile->netfid = netfid; pCifsFile->invalidHandle = false; up(&pCifsFile->fh_sem); @@ -439,7 +485,7 @@ reopen_error_exit: go to server to get inode info */ pCifsInode->clientCanCacheAll = false; pCifsInode->clientCanCacheRead = false; - if (pTcon->unix_ext) + if (tcon->unix_ext) rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, xid); else @@ -467,7 +513,6 @@ reopen_error_exit: cifs_relock_file(pCifsFile); } } - kfree(full_path); FreeXid(xid); return rc;