X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fcifs%2Ffile.c;h=e2b4ce1dad6680cc54d8af516e7cf876533361fd;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=ddb012a68023fe0818d50670f2fb81a990dbab56;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ddb012a68..e2b4ce1da 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -5,7 +5,6 @@ * * 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 @@ -48,8 +47,6 @@ 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; @@ -113,6 +110,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, &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 */ @@ -203,7 +201,7 @@ int cifs_open(struct inode *inode, struct file *file) } else { if (file->f_flags & O_EXCL) cERROR(1, ("could not find file instance for " - "new file %p", file)); + "new file %p ", file)); } } @@ -262,15 +260,10 @@ int cifs_open(struct inode *inode, struct file *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, @@ -279,7 +272,7 @@ int cifs_open(struct inode *inode, struct file *file) & 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 = @@ -289,6 +282,7 @@ int cifs_open(struct inode *inode, struct file *file) 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); @@ -299,6 +293,7 @@ int cifs_open(struct inode *inode, struct file *file) &oplock, buf, full_path, xid); } else { write_unlock(&GlobalSMBSeslock); + write_unlock(&file->f_owner.lock); } if (oplock & CIFS_CREATE_ACTION) { @@ -327,7 +322,7 @@ out: 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) { @@ -414,8 +409,8 @@ static int cifs_reopen_file(struct inode *inode, struct file *file, 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; @@ -476,9 +471,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; + write_lock(&file->f_owner.lock); if (pTcon) { /* no sense reconnecting to close a file that is already closed */ @@ -493,28 +487,23 @@ int cifs_close(struct inode *inode, struct file *file) 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; @@ -542,7 +531,7 @@ int cifs_closedir(struct inode *inode, struct file *file) (struct cifsFileInfo *)file->private_data; char *ptmp; - cFYI(1, ("Closedir inode = 0x%p", inode)); + cFYI(1, ("Closedir inode = 0x%p with ", inode)); xid = GetXid(); @@ -585,21 +574,6 @@ 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; @@ -611,7 +585,6 @@ 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; @@ -632,7 +605,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) } 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 & @@ -670,14 +643,15 @@ 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(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; @@ -713,15 +687,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 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; @@ -730,47 +699,18 @@ 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 { - 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); @@ -1139,9 +1079,9 @@ static int cifs_writepages(struct address_space *mapping, 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; @@ -1182,14 +1122,16 @@ static int cifs_writepages(struct address_space *mapping, 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: @@ -1225,7 +1167,7 @@ retry: break; } - if (!wbc->range_cyclic && page->index > end) { + if (unlikely(is_range) && (page->index > end)) { done = 1; unlock_page(page); break; @@ -1329,7 +1271,7 @@ retry: index = 0; goto retry; } - if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) + if (!is_range) mapping->writeback_index = index; FreeXid(xid); @@ -1435,7 +1377,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) 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); @@ -1464,7 +1406,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) /* 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) @@ -1477,7 +1419,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) * 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; @@ -1896,7 +1838,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page, 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); @@ -2006,7 +1948,7 @@ static int cifs_prepare_write(struct file *file, struct page *page, 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, @@ -2017,19 +1959,3 @@ const struct address_space_operations cifs_addr_ops = { /* .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 = */ -};