*
* 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
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;
&pCifsInode->openFileList);
}
write_unlock(&GlobalSMBSeslock);
+ write_unlock(&file->f_owner.lock);
if (pCifsInode->clientCanCacheRead) {
/* we have the inode open somewhere else
no need to discard cache data */
} else {
if (file->f_flags & O_EXCL)
cERROR(1, ("could not find file instance for "
- "new file %p", file));
+ "new file %p ", file));
}
}
rc = -ENOMEM;
goto out;
}
-
- if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
- rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
- desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
+ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
+ CREATE_NOT_DIR, &netfid, &oplock, buf,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
& CIFS_MOUNT_MAP_SPECIAL_CHR);
- else
- rc = -EIO; /* no NT SMB support fall into legacy open below */
-
if (rc == -EIO) {
/* Old server, try legacy style OpenX */
rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
& CIFS_MOUNT_MAP_SPECIAL_CHR);
}
if (rc) {
- cFYI(1, ("cifs_open returned 0x%x", rc));
+ cFYI(1, ("cifs_open returned 0x%x ", rc));
goto out;
}
file->private_data =
goto out;
}
pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
+ write_lock(&file->f_owner.lock);
write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist, &pTcon->openFileList);
&oplock, buf, full_path, xid);
} else {
write_unlock(&GlobalSMBSeslock);
+ write_unlock(&file->f_owner.lock);
}
if (oplock & CIFS_CREATE_ACTION) {
return rc;
}
-/* Try to reacquire byte range locks that were released when session */
+/* Try to reaquire byte range locks that were released when session */
/* to server was lost */
static int cifs_relock_file(struct cifsFileInfo *cifsFile)
{
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
up(&pCifsFile->fh_sem);
- cFYI(1, ("cifs_open returned 0x%x", rc));
- cFYI(1, ("oplock: %d", oplock));
+ cFYI(1, ("cifs_open returned 0x%x ", rc));
+ cFYI(1, ("oplock: %d ", oplock));
} else {
pCifsFile->netfid = netfid;
pCifsFile->invalidHandle = FALSE;
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
if (pSMBFile) {
- struct cifsLockInfo *li, *tmp;
-
pSMBFile->closePend = TRUE;
+ write_lock(&file->f_owner.lock);
if (pTcon) {
/* no sense reconnecting to close a file that is
already closed */
the struct would be in each open file,
but this should give enough time to
clear the socket */
+ write_unlock(&file->f_owner.lock);
cERROR(1,("close with pending writes"));
msleep(timeout);
+ write_lock(&file->f_owner.lock);
timeout *= 4;
}
+ write_unlock(&file->f_owner.lock);
rc = CIFSSMBClose(xid, pTcon,
pSMBFile->netfid);
+ write_lock(&file->f_owner.lock);
}
}
-
- /* 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);
write_unlock(&GlobalSMBSeslock);
+ write_unlock(&file->f_owner.lock);
kfree(pSMBFile->search_resume_name);
kfree(file->private_data);
file->private_data = NULL;
(struct cifsFileInfo *)file->private_data;
char *ptmp;
- cFYI(1, ("Closedir inode = 0x%p", inode));
+ cFYI(1, ("Closedir inode = 0x%p with ", inode));
xid = GetXid();
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;
struct cifsTconInfo *pTcon;
__u16 netfid;
__u8 lockType = LOCKING_ANDX_LARGE_FILES;
- int posix_locking;
length = 1 + pfLock->fl_end - pfLock->fl_start;
rc = -EACCES;
}
if (pfLock->fl_flags & FL_ACCESS)
cFYI(1, ("Process suspended by mandatory locking - "
- "not implemented yet"));
+ "not implemented yet "));
if (pfLock->fl_flags & FL_LEASE)
cFYI(1, ("Lease on file - not implemented yet"));
if (pfLock->fl_flags &
}
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(posix_locking) {
+ if(experimEnabled &&
+ (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+ (CIFS_UNIX_FCNTL_CAP &
+ le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK;
FreeXid(xid);
return rc;
}
-
- 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) {
+ if (experimEnabled &&
+ (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+ (CIFS_UNIX_FCNTL_CAP &
+ le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK;
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 {
- 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;
-
- rc = 0;
- 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);
- }
- }
-
+ } else
+ rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
+ numUnlock, numLock, lockType, wait_flag);
if (pfLock->fl_flags & FL_POSIX)
posix_lock_file_wait(file, pfLock);
FreeXid(xid);
unsigned int bytes_written;
struct cifs_sb_info *cifs_sb;
int done = 0;
- pgoff_t end;
+ pgoff_t end = -1;
pgoff_t index;
- int range_whole = 0;
+ int is_range = 0;
struct kvec iov[32];
int len;
int n_iov = 0;
xid = GetXid();
pagevec_init(&pvec, 0);
- if (wbc->range_cyclic) {
+ if (wbc->sync_mode == WB_SYNC_NONE)
index = mapping->writeback_index; /* Start from prev offset */
- end = -1;
- } else {
- index = wbc->range_start >> PAGE_CACHE_SHIFT;
- end = wbc->range_end >> PAGE_CACHE_SHIFT;
- if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
- range_whole = 1;
+ else {
+ index = 0;
+ scanned = 1;
+ }
+ if (wbc->start || wbc->end) {
+ index = wbc->start >> PAGE_CACHE_SHIFT;
+ end = wbc->end >> PAGE_CACHE_SHIFT;
+ is_range = 1;
scanned = 1;
}
retry:
break;
}
- if (!wbc->range_cyclic && page->index > end) {
+ if (unlikely(is_range) && (page->index > end)) {
done = 1;
unlock_page(page);
break;
index = 0;
goto retry;
}
- if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
+ if (!is_range)
mapping->writeback_index = index;
FreeXid(xid);
xid = GetXid();
- cFYI(1, ("Sync file - name: %s datasync: 0x%x",
+ cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
dentry->d_name.name, datasync));
rc = filemap_fdatawrite(inode->i_mapping);
/* fill in rpages then
result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
-/* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index));
+/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
#if 0
if (rc < 0)
* As file closes, flush all cached write data for this inode checking
* for write behind errors.
*/
-int cifs_flush(struct file *file, fl_owner_t id)
+int cifs_flush(struct file *file)
{
struct inode * inode = file->f_dentry->d_inode;
int rc = 0;
if (rc < 0)
goto io_error;
else
- cFYI(1, ("Bytes read %d",rc));
+ cFYI(1, ("Bytes read %d ",rc));
file->f_dentry->d_inode->i_atime =
current_fs_time(file->f_dentry->d_inode->i_sb);
return 0;
}
-const struct address_space_operations cifs_addr_ops = {
+struct address_space_operations cifs_addr_ops = {
.readpage = cifs_readpage,
.readpages = cifs_readpages,
.writepage = cifs_writepage,
/* .sync_page = cifs_sync_page, */
/* .direct_IO = */
};
-
-/*
- * cifs_readpages requires the server to support a buffer large enough to
- * contain the header plus one complete page of data. Otherwise, we need
- * to leave cifs_readpages out of the address space operations.
- */
-const struct address_space_operations cifs_addr_ops_smallbuf = {
- .readpage = cifs_readpage,
- .writepage = cifs_writepage,
- .writepages = cifs_writepages,
- .prepare_write = cifs_prepare_write,
- .commit_write = cifs_commit_write,
- .set_page_dirty = __set_page_dirty_nobuffers,
- /* .sync_page = cifs_sync_page, */
- /* .direct_IO = */
-};