Commit 1dc1f94e authored by Evgeny Sinelnikov's avatar Evgeny Sinelnikov

Fixed fd duplicate problem with locks for 2.6.30

parent 77b1f340
...@@ -55,7 +55,7 @@ void cifs_dfs_release_automount_timer(void) ...@@ -55,7 +55,7 @@ void cifs_dfs_release_automount_timer(void)
* i.e. strips from UNC trailing path that is not part of share * i.e. strips from UNC trailing path that is not part of share
* name and fixup missing '\' in the begining of DFS node refferal * name and fixup missing '\' in the begining of DFS node refferal
* if neccessary. * if neccessary.
* Returns pointer to share name on success or NULL on error. * Returns pointer to share name on success or ERR_PTR on error.
* Caller is responsible for freeing returned string. * Caller is responsible for freeing returned string.
*/ */
static char *cifs_get_share_name(const char *node_name) static char *cifs_get_share_name(const char *node_name)
...@@ -68,7 +68,7 @@ static char *cifs_get_share_name(const char *node_name) ...@@ -68,7 +68,7 @@ static char *cifs_get_share_name(const char *node_name)
UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */, UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */,
GFP_KERNEL); GFP_KERNEL);
if (!UNC) if (!UNC)
return NULL; return ERR_PTR(-ENOMEM);
/* get share name and server name */ /* get share name and server name */
if (node_name[1] != '\\') { if (node_name[1] != '\\') {
...@@ -87,7 +87,7 @@ static char *cifs_get_share_name(const char *node_name) ...@@ -87,7 +87,7 @@ static char *cifs_get_share_name(const char *node_name)
cERROR(1, ("%s: no server name end in node name: %s", cERROR(1, ("%s: no server name end in node name: %s",
__func__, node_name)); __func__, node_name));
kfree(UNC); kfree(UNC);
return NULL; return ERR_PTR(-EINVAL);
} }
/* find sharename end */ /* find sharename end */
...@@ -133,6 +133,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata, ...@@ -133,6 +133,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
*devname = cifs_get_share_name(ref->node_name); *devname = cifs_get_share_name(ref->node_name);
if (IS_ERR(*devname)) {
rc = PTR_ERR(*devname);
*devname = NULL;
goto compose_mount_options_err;
}
rc = dns_resolve_server_name_to_ip(*devname, &srvIP); rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
if (rc != 0) { if (rc != 0) {
cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d", cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d",
......
...@@ -970,6 +970,7 @@ static int cifs_oplock_thread(void *dummyarg) ...@@ -970,6 +970,7 @@ static int cifs_oplock_thread(void *dummyarg)
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct inode *inode; struct inode *inode;
__u16 netfid; __u16 netfid;
__u32 netpid;
int rc, waitrc = 0; int rc, waitrc = 0;
set_freezable(); set_freezable();
...@@ -989,6 +990,7 @@ static int cifs_oplock_thread(void *dummyarg) ...@@ -989,6 +990,7 @@ static int cifs_oplock_thread(void *dummyarg)
pTcon = oplock_item->tcon; pTcon = oplock_item->tcon;
inode = oplock_item->pinode; inode = oplock_item->pinode;
netfid = oplock_item->netfid; netfid = oplock_item->netfid;
netpid = oplock_item->netpid;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
DeleteOplockQEntry(oplock_item); DeleteOplockQEntry(oplock_item);
/* can not grab inode sem here since it would /* can not grab inode sem here since it would
...@@ -1026,7 +1028,7 @@ static int cifs_oplock_thread(void *dummyarg) ...@@ -1026,7 +1028,7 @@ static int cifs_oplock_thread(void *dummyarg)
to server still is disconnected since oplock to server still is disconnected since oplock
already released by the server in that case */ already released by the server in that case */
if (!pTcon->need_reconnect) { if (!pTcon->need_reconnect) {
rc = CIFSSMBLock(0, pTcon, netfid, rc = CIFSSMBLock(0, pTcon, netfid, netpid,
0 /* len */ , 0 /* offset */, 0, 0 /* len */ , 0 /* offset */, 0,
0, LOCKING_ANDX_OPLOCK_RELEASE, 0, LOCKING_ANDX_OPLOCK_RELEASE,
false /* wait flag */); false /* wait flag */);
......
...@@ -448,6 +448,7 @@ struct oplock_q_entry { ...@@ -448,6 +448,7 @@ struct oplock_q_entry {
struct inode *pinode; struct inode *pinode;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
__u16 netfid; __u16 netfid;
__u32 netpid;
}; };
/* for pending dnotify requests */ /* for pending dnotify requests */
...@@ -545,9 +546,9 @@ require use of the stronger protocol */ ...@@ -545,9 +546,9 @@ require use of the stronger protocol */
#define CIFSSEC_MUST_LANMAN 0x10010 #define CIFSSEC_MUST_LANMAN 0x10010
#define CIFSSEC_MUST_PLNTXT 0x20020 #define CIFSSEC_MUST_PLNTXT 0x20020
#ifdef CONFIG_CIFS_UPCALL #ifdef CONFIG_CIFS_UPCALL
#define CIFSSEC_MASK 0xAF0AF /* allows weak security but also krb5 */ #define CIFSSEC_MASK 0xBF0BF /* allows weak security but also krb5 */
#else #else
#define CIFSSEC_MASK 0xA70A7 /* current flags supported if weak */ #define CIFSSEC_MASK 0xB70B7 /* current flags supported if weak */
#endif /* UPCALL */ #endif /* UPCALL */
#else /* do not allow weak pw hash */ #else /* do not allow weak pw hash */
#ifdef CONFIG_CIFS_UPCALL #ifdef CONFIG_CIFS_UPCALL
......
...@@ -86,7 +86,7 @@ extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -86,7 +86,7 @@ extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
const int stage, const int stage,
const struct nls_table *nls_cp); const struct nls_table *nls_cp);
extern __u16 GetNextMid(struct TCP_Server_Info *server); extern __u16 GetNextMid(struct TCP_Server_Info *server);
extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16, extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16, __u32,
struct cifsTconInfo *); struct cifsTconInfo *);
extern void DeleteOplockQEntry(struct oplock_q_entry *); extern void DeleteOplockQEntry(struct oplock_q_entry *);
extern void DeleteTconOplockQEntries(struct cifsTconInfo *); extern void DeleteTconOplockQEntries(struct cifsTconInfo *);
...@@ -310,12 +310,12 @@ extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, ...@@ -310,12 +310,12 @@ extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
const struct nls_table *cp, int mapChars); const struct nls_table *cp, int mapChars);
extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 netfid, const __u64 len, const __u16 netfid, const __u32 netpid, const __u64 len,
const __u64 offset, const __u32 numUnlock, const __u64 offset, const __u32 numUnlock,
const __u32 numLock, const __u8 lockType, const __u32 numLock, const __u8 lockType,
const bool waitFlag); const bool waitFlag);
extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const int get_flag, const __u16 smb_file_id, const __u32 netpid, const int get_flag,
const __u64 len, struct file_lock *, const __u64 len, struct file_lock *,
const __u16 lock_type, const bool waitFlag); const __u16 lock_type, const bool waitFlag);
extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
......
...@@ -1689,7 +1689,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, ...@@ -1689,7 +1689,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
int int
CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const __u64 len, const __u16 smb_file_id, const __u32 net_pid, const __u64 len,
const __u64 offset, const __u32 numUnlock, const __u64 offset, const __u32 numUnlock,
const __u32 numLock, const __u8 lockType, const bool waitFlag) const __u32 numLock, const __u8 lockType, const bool waitFlag)
{ {
...@@ -1723,7 +1723,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, ...@@ -1723,7 +1723,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
pSMB->Fid = smb_file_id; /* netfid stays le */ pSMB->Fid = smb_file_id; /* netfid stays le */
if ((numLock != 0) || (numUnlock != 0)) { if ((numLock != 0) || (numUnlock != 0)) {
pSMB->Locks[0].Pid = cpu_to_le16(current->tgid); pSMB->Locks[0].Pid = cpu_to_le16(net_pid);
/* BB where to store pid high? */ /* BB where to store pid high? */
pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len); pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32)); pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
...@@ -1757,7 +1757,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, ...@@ -1757,7 +1757,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
int int
CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const int get_flag, const __u64 len, const __u16 smb_file_id, const __u32 net_pid, const int get_flag, const __u64 len,
struct file_lock *pLockData, const __u16 lock_type, struct file_lock *pLockData, const __u16 lock_type,
const bool waitFlag) const bool waitFlag)
{ {
...@@ -1817,7 +1817,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, ...@@ -1817,7 +1817,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
} else } else
pSMB->Timeout = 0; pSMB->Timeout = 0;
parm_data->pid = cpu_to_le32(current->tgid); parm_data->pid = cpu_to_le32(net_pid);
parm_data->start = cpu_to_le64(pLockData->fl_start); parm_data->start = cpu_to_le64(pLockData->fl_start);
parm_data->length = cpu_to_le64(len); /* normalize negative numbers */ parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
......
...@@ -2569,11 +2569,20 @@ remote_path_check: ...@@ -2569,11 +2569,20 @@ remote_path_check:
if (mount_data != mount_data_global) if (mount_data != mount_data_global)
kfree(mount_data); kfree(mount_data);
mount_data = cifs_compose_mount_options( mount_data = cifs_compose_mount_options(
cifs_sb->mountdata, full_path + 1, cifs_sb->mountdata, full_path + 1,
referrals, &fake_devname); referrals, &fake_devname);
kfree(fake_devname);
free_dfs_info_array(referrals, num_referrals); free_dfs_info_array(referrals, num_referrals);
kfree(fake_devname);
kfree(full_path);
if (IS_ERR(mount_data)) {
rc = PTR_ERR(mount_data);
mount_data = NULL;
goto mount_fail_check;
}
if (tcon) if (tcon)
cifs_put_tcon(tcon); cifs_put_tcon(tcon);
...@@ -2581,8 +2590,6 @@ remote_path_check: ...@@ -2581,8 +2590,6 @@ remote_path_check:
cifs_put_smb_ses(pSesInfo); cifs_put_smb_ses(pSesInfo);
cleanup_volume_info(&volume_info); cleanup_volume_info(&volume_info);
FreeXid(xid);
kfree(full_path);
referral_walks_count++; referral_walks_count++;
goto try_mount_again; goto try_mount_again;
} }
......
...@@ -798,6 +798,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -798,6 +798,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
bool wait_flag = false; bool wait_flag = false;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
__u32 netpid;
__u16 netfid; __u16 netfid;
__u8 lockType = LOCKING_ANDX_LARGE_FILES; __u8 lockType = LOCKING_ANDX_LARGE_FILES;
bool posix_locking = 0; bool posix_locking = 0;
...@@ -857,6 +858,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -857,6 +858,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
FreeXid(xid); FreeXid(xid);
return -EBADF; return -EBADF;
} }
netpid = ((struct cifsFileInfo *)file->private_data)->pid;
netfid = ((struct cifsFileInfo *)file->private_data)->netfid; netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
if ((tcon->ses->capabilities & CAP_UNIX) && if ((tcon->ses->capabilities & CAP_UNIX) &&
...@@ -873,7 +875,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -873,7 +875,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
posix_lock_type = CIFS_RDLCK; posix_lock_type = CIFS_RDLCK;
else else
posix_lock_type = CIFS_WRLCK; posix_lock_type = CIFS_WRLCK;
rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */, rc = CIFSSMBPosixLock(xid, tcon, netfid, netpid, 1 /* get */,
length, pfLock, length, pfLock,
posix_lock_type, wait_flag); posix_lock_type, wait_flag);
FreeXid(xid); FreeXid(xid);
...@@ -881,10 +883,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -881,10 +883,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
} }
/* BB we could chain these into one lock request BB */ /* BB we could chain these into one lock request BB */
rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, rc = CIFSSMBLock(xid, tcon, netfid, netpid, length, pfLock->fl_start,
0, 1, lockType, 0 /* wait flag */ ); 0, 1, lockType, 0 /* wait flag */ );
if (rc == 0) { if (rc == 0) {
rc = CIFSSMBLock(xid, tcon, netfid, length, rc = CIFSSMBLock(xid, tcon, netfid, netpid, length,
pfLock->fl_start, 1 /* numUnlock */ , pfLock->fl_start, 1 /* numUnlock */ ,
0 /* numLock */ , lockType, 0 /* numLock */ , lockType,
0 /* wait flag */ ); 0 /* wait flag */ );
...@@ -901,12 +903,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -901,12 +903,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if (lockType & LOCKING_ANDX_SHARED_LOCK) { if (lockType & LOCKING_ANDX_SHARED_LOCK) {
pfLock->fl_type = F_WRLCK; pfLock->fl_type = F_WRLCK;
} else { } else {
rc = CIFSSMBLock(xid, tcon, netfid, length, rc = CIFSSMBLock(xid, tcon, netfid, netpid, length,
pfLock->fl_start, 0, 1, pfLock->fl_start, 0, 1,
lockType | LOCKING_ANDX_SHARED_LOCK, lockType | LOCKING_ANDX_SHARED_LOCK,
0 /* wait flag */ ); 0 /* wait flag */ );
if (rc == 0) { if (rc == 0) {
rc = CIFSSMBLock(xid, tcon, netfid, rc = CIFSSMBLock(xid, tcon, netfid, netpid,
length, pfLock->fl_start, 1, 0, length, pfLock->fl_start, 1, 0,
lockType | lockType |
LOCKING_ANDX_SHARED_LOCK, LOCKING_ANDX_SHARED_LOCK,
...@@ -945,7 +947,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -945,7 +947,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if (numUnlock == 1) if (numUnlock == 1)
posix_lock_type = CIFS_UNLCK; posix_lock_type = CIFS_UNLCK;
rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */, rc = CIFSSMBPosixLock(xid, tcon, netfid, netpid, 0 /* set */,
length, pfLock, length, pfLock,
posix_lock_type, wait_flag); posix_lock_type, wait_flag);
} else { } else {
...@@ -953,7 +955,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -953,7 +955,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
(struct cifsFileInfo *)file->private_data; (struct cifsFileInfo *)file->private_data;
if (numLock) { if (numLock) {
rc = CIFSSMBLock(xid, tcon, netfid, length, rc = CIFSSMBLock(xid, tcon, netfid, netpid, length,
pfLock->fl_start, pfLock->fl_start,
0, numLock, lockType, wait_flag); 0, numLock, lockType, wait_flag);
...@@ -975,7 +977,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -975,7 +977,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
(pfLock->fl_start + length) >= (pfLock->fl_start + length) >=
(li->offset + li->length)) { (li->offset + li->length)) {
stored_rc = CIFSSMBLock(xid, tcon, stored_rc = CIFSSMBLock(xid, tcon,
netfid, netfid, netpid,
li->length, li->offset, li->length, li->offset,
1, 0, li->type, false); 1, 0, li->type, false);
if (stored_rc) if (stored_rc)
......
...@@ -578,7 +578,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) ...@@ -578,7 +578,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
pCifsInode->clientCanCacheRead = false; pCifsInode->clientCanCacheRead = false;
pCifsInode->oplockPending = true; pCifsInode->oplockPending = true;
AllocOplockQEntry(netfile->pInode, AllocOplockQEntry(netfile->pInode,
netfile->netfid, tcon); netfile->netfid, netfile->pid, tcon);
cFYI(1, ("about to wake up oplock thread")); cFYI(1, ("about to wake up oplock thread"));
if (oplockThread) if (oplockThread)
wake_up_process(oplockThread); wake_up_process(oplockThread);
......
...@@ -104,7 +104,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) ...@@ -104,7 +104,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
} }
struct oplock_q_entry * struct oplock_q_entry *
AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon) AllocOplockQEntry(struct inode *pinode, __u16 fid, __u32 pid, struct cifsTconInfo *tcon)
{ {
struct oplock_q_entry *temp; struct oplock_q_entry *temp;
if ((pinode == NULL) || (tcon == NULL)) { if ((pinode == NULL) || (tcon == NULL)) {
...@@ -119,6 +119,7 @@ AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon) ...@@ -119,6 +119,7 @@ AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
temp->pinode = pinode; temp->pinode = pinode;
temp->tcon = tcon; temp->tcon = tcon;
temp->netfid = fid; temp->netfid = fid;
temp->netpid = pid;
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
list_add_tail(&temp->qhead, &GlobalOplock_Q); list_add_tail(&temp->qhead, &GlobalOplock_Q);
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment