Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 33676
b: refs/heads/master
c: 7ee1af7
h: refs/heads/master
v: v3
  • Loading branch information
Jeremy Allison authored and Steve French committed Aug 11, 2006
1 parent 7abbdca commit 96b0add
Show file tree
Hide file tree
Showing 8 changed files with 513 additions and 297 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6c3d8909d85b2c18fd7a6e64f0ca757a257b40fa
refs/heads/master: 7ee1af765dfa3146aef958258003245e082284e5
15 changes: 9 additions & 6 deletions trunk/fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*
* Copyright (C) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
Expand Down Expand Up @@ -267,14 +268,14 @@ struct cifsTconInfo {
};

/*
* This info hangs off the cifsFileInfo structure. This is used to track
* byte stream locks on the file
* This info hangs off the cifsFileInfo structure, pointed to by llist.
* This is used to track byte stream locks on the file
*/
struct cifsLockInfo {
struct cifsLockInfo *next;
int start;
int length;
int type;
struct list_head llist; /* pointer to next cifsLockInfo */
__u64 offset;
__u64 length;
__u8 type;
};

/*
Expand Down Expand Up @@ -305,6 +306,8 @@ struct cifsFileInfo {
/* lock scope id (0 if none) */
struct file * pfile; /* needed for writepage */
struct inode * pInode; /* needed for oplock break */
struct semaphore lock_sem;
struct list_head llist; /* list of byte range locks we have. */
unsigned closePend:1; /* file is marked to close */
unsigned invalidHandle:1; /* file closed via session abend */
atomic_t wrtPending; /* handle in use - defer close */
Expand Down
4 changes: 4 additions & 0 deletions trunk/fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
struct kvec *, int /* nvec to send */,
int * /* type of buf returned */ , const int long_op);
extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *,
struct smb_hdr * /* input */ ,
struct smb_hdr * /* out */ ,
int * /* bytes returned */);
extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
Expand Down
15 changes: 13 additions & 2 deletions trunk/fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1460,8 +1460,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
pSMB->hdr.smb_buf_length += count;
pSMB->ByteCount = cpu_to_le16(count);

rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
if (waitFlag) {
rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned);
} else {
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, timeout);
}
cifs_stats_inc(&tcon->num_locks);
if (rc) {
cFYI(1, ("Send error in Lock = %d", rc));
Expand Down Expand Up @@ -1546,8 +1551,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
if (waitFlag) {
rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned);
} else {
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, timeout);
}

if (rc) {
cFYI(1, ("Send error in Posix Lock = %d", rc));
} else if (get_flag) {
Expand Down
95 changes: 80 additions & 15 deletions trunk/fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*
* Copyright (C) International Business Machines Corp., 2002,2003
* Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
Expand Down Expand Up @@ -47,6 +48,8 @@ static inline struct cifsFileInfo *cifs_init_private(
private_data->netfid = netfid;
private_data->pid = current->tgid;
init_MUTEX(&private_data->fh_sem);
init_MUTEX(&private_data->lock_sem);
INIT_LIST_HEAD(&private_data->llist);
private_data->pfile = file; /* needed for writepage */
private_data->pInode = inode;
private_data->invalidHandle = FALSE;
Expand Down Expand Up @@ -473,6 +476,8 @@ int cifs_close(struct inode *inode, struct file *file)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
if (pSMBFile) {
struct cifsLockInfo *li, *tmp;

pSMBFile->closePend = TRUE;
if (pTcon) {
/* no sense reconnecting to close a file that is
Expand All @@ -496,6 +501,16 @@ int cifs_close(struct inode *inode, struct file *file)
pSMBFile->netfid);
}
}

/* Delete any outstanding lock records.
We'll lose them when the file is closed anyway. */
down(&pSMBFile->lock_sem);
list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
list_del(&li->llist);
kfree(li);
}
up(&pSMBFile->lock_sem);

write_lock(&GlobalSMBSeslock);
list_del(&pSMBFile->flist);
list_del(&pSMBFile->tlist);
Expand Down Expand Up @@ -570,6 +585,21 @@ int cifs_closedir(struct inode *inode, struct file *file)
return rc;
}

static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
__u64 offset, __u8 lockType)
{
struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
if (li == NULL)
return -ENOMEM;
li->offset = offset;
li->length = len;
li->type = lockType;
down(&fid->lock_sem);
list_add(&li->llist, &fid->llist);
up(&fid->lock_sem);
return 0;
}

int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
{
int rc, xid;
Expand All @@ -581,6 +611,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
struct cifsTconInfo *pTcon;
__u16 netfid;
__u8 lockType = LOCKING_ANDX_LARGE_FILES;
int posix_locking;

length = 1 + pfLock->fl_end - pfLock->fl_start;
rc = -EACCES;
Expand Down Expand Up @@ -639,14 +670,14 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
}
netfid = ((struct cifsFileInfo *)file->private_data)->netfid;

posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability));

/* BB add code here to normalize offset and length to
account for negative length which we can not accept over the
wire */
if (IS_GETLK(cmd)) {
if((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_FCNTL_CAP &
le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
if(posix_locking) {
int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK;
Expand Down Expand Up @@ -682,9 +713,15 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
FreeXid(xid);
return rc;
}
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_FCNTL_CAP &
le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {

if (!numLock && !numUnlock) {
/* if no lock or unlock then nothing
to do since we do not know what it is */
FreeXid(xid);
return -EOPNOTSUPP;
}

if (posix_locking) {
int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK;
Expand All @@ -693,18 +730,46 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)

if(numUnlock == 1)
posix_lock_type = CIFS_UNLCK;
else if(numLock == 0) {
/* if no lock or unlock then nothing
to do since we do not know what it is */
FreeXid(xid);
return -EOPNOTSUPP;
}

rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
length, pfLock,
posix_lock_type, wait_flag);
} else
rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
numUnlock, numLock, lockType, wait_flag);
} else {
struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;

if (numLock) {
rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
0, numLock, lockType, wait_flag);

if (rc == 0) {
/* For Windows locks we must store them. */
rc = store_file_lock(fid, length,
pfLock->fl_start, lockType);
}
} else if (numUnlock) {
/* For each stored lock that this unlock overlaps
completely, unlock it. */
int stored_rc = 0;
struct cifsLockInfo *li, *tmp;

down(&fid->lock_sem);
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
if (pfLock->fl_start <= li->offset &&
length >= li->length) {
stored_rc = CIFSSMBLock(xid, pTcon, netfid,
li->length, li->offset,
1, 0, li->type, FALSE);
if (stored_rc)
rc = stored_rc;

list_del(&li->llist);
kfree(li);
}
}
up(&fid->lock_sem);
}
}

if (pfLock->fl_flags & FL_POSIX)
posix_lock_file_wait(file, pfLock);
FreeXid(xid);
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/cifs/netmisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{ERRinvlevel,-EOPNOTSUPP},
{ERRdirnotempty, -ENOTEMPTY},
{ERRnotlocked, -ENOLCK},
{ERRcancelviolation, -ENOLCK},
{ERRalreadyexists, -EEXIST},
{ERRmoredata, -EOVERFLOW},
{ERReasnotsupported,-EOPNOTSUPP},
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/cifs/smberr.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
#define ERRinvlevel 124
#define ERRdirnotempty 145
#define ERRnotlocked 158
#define ERRcancelviolation 173
#define ERRalreadyexists 183
#define ERRbadpipe 230
#define ERRpipebusy 231
Expand Down
Loading

0 comments on commit 96b0add

Please sign in to comment.