aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c154
1 files changed, 115 insertions, 39 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index b4a18c1cab0a..ddb012a68023 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2002,2003 6 * Copyright (C) International Business Machines Corp., 2002,2003
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * Jeremy Allison (jra@samba.org)
8 * 9 *
9 * This library is free software; you can redistribute it and/or modify 10 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published 11 * it under the terms of the GNU Lesser General Public License as published
@@ -47,6 +48,8 @@ static inline struct cifsFileInfo *cifs_init_private(
47 private_data->netfid = netfid; 48 private_data->netfid = netfid;
48 private_data->pid = current->tgid; 49 private_data->pid = current->tgid;
49 init_MUTEX(&private_data->fh_sem); 50 init_MUTEX(&private_data->fh_sem);
51 init_MUTEX(&private_data->lock_sem);
52 INIT_LIST_HEAD(&private_data->llist);
50 private_data->pfile = file; /* needed for writepage */ 53 private_data->pfile = file; /* needed for writepage */
51 private_data->pInode = inode; 54 private_data->pInode = inode;
52 private_data->invalidHandle = FALSE; 55 private_data->invalidHandle = FALSE;
@@ -110,7 +113,6 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
110 &pCifsInode->openFileList); 113 &pCifsInode->openFileList);
111 } 114 }
112 write_unlock(&GlobalSMBSeslock); 115 write_unlock(&GlobalSMBSeslock);
113 write_unlock(&file->f_owner.lock);
114 if (pCifsInode->clientCanCacheRead) { 116 if (pCifsInode->clientCanCacheRead) {
115 /* we have the inode open somewhere else 117 /* we have the inode open somewhere else
116 no need to discard cache data */ 118 no need to discard cache data */
@@ -201,7 +203,7 @@ int cifs_open(struct inode *inode, struct file *file)
201 } else { 203 } else {
202 if (file->f_flags & O_EXCL) 204 if (file->f_flags & O_EXCL)
203 cERROR(1, ("could not find file instance for " 205 cERROR(1, ("could not find file instance for "
204 "new file %p ", file)); 206 "new file %p", file));
205 } 207 }
206 } 208 }
207 209
@@ -260,10 +262,15 @@ int cifs_open(struct inode *inode, struct file *file)
260 rc = -ENOMEM; 262 rc = -ENOMEM;
261 goto out; 263 goto out;
262 } 264 }
263 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, 265
264 CREATE_NOT_DIR, &netfid, &oplock, buf, 266 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
267 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
268 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
265 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 269 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
266 & CIFS_MOUNT_MAP_SPECIAL_CHR); 270 & CIFS_MOUNT_MAP_SPECIAL_CHR);
271 else
272 rc = -EIO; /* no NT SMB support fall into legacy open below */
273
267 if (rc == -EIO) { 274 if (rc == -EIO) {
268 /* Old server, try legacy style OpenX */ 275 /* Old server, try legacy style OpenX */
269 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, 276 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
@@ -272,7 +279,7 @@ int cifs_open(struct inode *inode, struct file *file)
272 & CIFS_MOUNT_MAP_SPECIAL_CHR); 279 & CIFS_MOUNT_MAP_SPECIAL_CHR);
273 } 280 }
274 if (rc) { 281 if (rc) {
275 cFYI(1, ("cifs_open returned 0x%x ", rc)); 282 cFYI(1, ("cifs_open returned 0x%x", rc));
276 goto out; 283 goto out;
277 } 284 }
278 file->private_data = 285 file->private_data =
@@ -282,7 +289,6 @@ int cifs_open(struct inode *inode, struct file *file)
282 goto out; 289 goto out;
283 } 290 }
284 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); 291 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
285 write_lock(&file->f_owner.lock);
286 write_lock(&GlobalSMBSeslock); 292 write_lock(&GlobalSMBSeslock);
287 list_add(&pCifsFile->tlist, &pTcon->openFileList); 293 list_add(&pCifsFile->tlist, &pTcon->openFileList);
288 294
@@ -293,7 +299,6 @@ int cifs_open(struct inode *inode, struct file *file)
293 &oplock, buf, full_path, xid); 299 &oplock, buf, full_path, xid);
294 } else { 300 } else {
295 write_unlock(&GlobalSMBSeslock); 301 write_unlock(&GlobalSMBSeslock);
296 write_unlock(&file->f_owner.lock);
297 } 302 }
298 303
299 if (oplock & CIFS_CREATE_ACTION) { 304 if (oplock & CIFS_CREATE_ACTION) {
@@ -322,7 +327,7 @@ out:
322 return rc; 327 return rc;
323} 328}
324 329
325/* Try to reaquire byte range locks that were released when session */ 330/* Try to reacquire byte range locks that were released when session */
326/* to server was lost */ 331/* to server was lost */
327static int cifs_relock_file(struct cifsFileInfo *cifsFile) 332static int cifs_relock_file(struct cifsFileInfo *cifsFile)
328{ 333{
@@ -409,8 +414,8 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
409 CIFS_MOUNT_MAP_SPECIAL_CHR); 414 CIFS_MOUNT_MAP_SPECIAL_CHR);
410 if (rc) { 415 if (rc) {
411 up(&pCifsFile->fh_sem); 416 up(&pCifsFile->fh_sem);
412 cFYI(1, ("cifs_open returned 0x%x ", rc)); 417 cFYI(1, ("cifs_open returned 0x%x", rc));
413 cFYI(1, ("oplock: %d ", oplock)); 418 cFYI(1, ("oplock: %d", oplock));
414 } else { 419 } else {
415 pCifsFile->netfid = netfid; 420 pCifsFile->netfid = netfid;
416 pCifsFile->invalidHandle = FALSE; 421 pCifsFile->invalidHandle = FALSE;
@@ -471,8 +476,9 @@ int cifs_close(struct inode *inode, struct file *file)
471 cifs_sb = CIFS_SB(inode->i_sb); 476 cifs_sb = CIFS_SB(inode->i_sb);
472 pTcon = cifs_sb->tcon; 477 pTcon = cifs_sb->tcon;
473 if (pSMBFile) { 478 if (pSMBFile) {
479 struct cifsLockInfo *li, *tmp;
480
474 pSMBFile->closePend = TRUE; 481 pSMBFile->closePend = TRUE;
475 write_lock(&file->f_owner.lock);
476 if (pTcon) { 482 if (pTcon) {
477 /* no sense reconnecting to close a file that is 483 /* no sense reconnecting to close a file that is
478 already closed */ 484 already closed */
@@ -487,23 +493,28 @@ int cifs_close(struct inode *inode, struct file *file)
487 the struct would be in each open file, 493 the struct would be in each open file,
488 but this should give enough time to 494 but this should give enough time to
489 clear the socket */ 495 clear the socket */
490 write_unlock(&file->f_owner.lock);
491 cERROR(1,("close with pending writes")); 496 cERROR(1,("close with pending writes"));
492 msleep(timeout); 497 msleep(timeout);
493 write_lock(&file->f_owner.lock);
494 timeout *= 4; 498 timeout *= 4;
495 } 499 }
496 write_unlock(&file->f_owner.lock);
497 rc = CIFSSMBClose(xid, pTcon, 500 rc = CIFSSMBClose(xid, pTcon,
498 pSMBFile->netfid); 501 pSMBFile->netfid);
499 write_lock(&file->f_owner.lock);
500 } 502 }
501 } 503 }
504
505 /* Delete any outstanding lock records.
506 We'll lose them when the file is closed anyway. */
507 down(&pSMBFile->lock_sem);
508 list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
509 list_del(&li->llist);
510 kfree(li);
511 }
512 up(&pSMBFile->lock_sem);
513
502 write_lock(&GlobalSMBSeslock); 514 write_lock(&GlobalSMBSeslock);
503 list_del(&pSMBFile->flist); 515 list_del(&pSMBFile->flist);
504 list_del(&pSMBFile->tlist); 516 list_del(&pSMBFile->tlist);
505 write_unlock(&GlobalSMBSeslock); 517 write_unlock(&GlobalSMBSeslock);
506 write_unlock(&file->f_owner.lock);
507 kfree(pSMBFile->search_resume_name); 518 kfree(pSMBFile->search_resume_name);
508 kfree(file->private_data); 519 kfree(file->private_data);
509 file->private_data = NULL; 520 file->private_data = NULL;
@@ -531,7 +542,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
531 (struct cifsFileInfo *)file->private_data; 542 (struct cifsFileInfo *)file->private_data;
532 char *ptmp; 543 char *ptmp;
533 544
534 cFYI(1, ("Closedir inode = 0x%p with ", inode)); 545 cFYI(1, ("Closedir inode = 0x%p", inode));
535 546
536 xid = GetXid(); 547 xid = GetXid();
537 548
@@ -574,6 +585,21 @@ int cifs_closedir(struct inode *inode, struct file *file)
574 return rc; 585 return rc;
575} 586}
576 587
588static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
589 __u64 offset, __u8 lockType)
590{
591 struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
592 if (li == NULL)
593 return -ENOMEM;
594 li->offset = offset;
595 li->length = len;
596 li->type = lockType;
597 down(&fid->lock_sem);
598 list_add(&li->llist, &fid->llist);
599 up(&fid->lock_sem);
600 return 0;
601}
602
577int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 603int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
578{ 604{
579 int rc, xid; 605 int rc, xid;
@@ -585,6 +611,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
585 struct cifsTconInfo *pTcon; 611 struct cifsTconInfo *pTcon;
586 __u16 netfid; 612 __u16 netfid;
587 __u8 lockType = LOCKING_ANDX_LARGE_FILES; 613 __u8 lockType = LOCKING_ANDX_LARGE_FILES;
614 int posix_locking;
588 615
589 length = 1 + pfLock->fl_end - pfLock->fl_start; 616 length = 1 + pfLock->fl_end - pfLock->fl_start;
590 rc = -EACCES; 617 rc = -EACCES;
@@ -605,7 +632,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
605 } 632 }
606 if (pfLock->fl_flags & FL_ACCESS) 633 if (pfLock->fl_flags & FL_ACCESS)
607 cFYI(1, ("Process suspended by mandatory locking - " 634 cFYI(1, ("Process suspended by mandatory locking - "
608 "not implemented yet ")); 635 "not implemented yet"));
609 if (pfLock->fl_flags & FL_LEASE) 636 if (pfLock->fl_flags & FL_LEASE)
610 cFYI(1, ("Lease on file - not implemented yet")); 637 cFYI(1, ("Lease on file - not implemented yet"));
611 if (pfLock->fl_flags & 638 if (pfLock->fl_flags &
@@ -643,15 +670,14 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
643 } 670 }
644 netfid = ((struct cifsFileInfo *)file->private_data)->netfid; 671 netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
645 672
673 posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
674 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability));
646 675
647 /* BB add code here to normalize offset and length to 676 /* BB add code here to normalize offset and length to
648 account for negative length which we can not accept over the 677 account for negative length which we can not accept over the
649 wire */ 678 wire */
650 if (IS_GETLK(cmd)) { 679 if (IS_GETLK(cmd)) {
651 if(experimEnabled && 680 if(posix_locking) {
652 (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
653 (CIFS_UNIX_FCNTL_CAP &
654 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
655 int posix_lock_type; 681 int posix_lock_type;
656 if(lockType & LOCKING_ANDX_SHARED_LOCK) 682 if(lockType & LOCKING_ANDX_SHARED_LOCK)
657 posix_lock_type = CIFS_RDLCK; 683 posix_lock_type = CIFS_RDLCK;
@@ -687,10 +713,15 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
687 FreeXid(xid); 713 FreeXid(xid);
688 return rc; 714 return rc;
689 } 715 }
690 if (experimEnabled && 716
691 (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && 717 if (!numLock && !numUnlock) {
692 (CIFS_UNIX_FCNTL_CAP & 718 /* if no lock or unlock then nothing
693 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { 719 to do since we do not know what it is */
720 FreeXid(xid);
721 return -EOPNOTSUPP;
722 }
723
724 if (posix_locking) {
694 int posix_lock_type; 725 int posix_lock_type;
695 if(lockType & LOCKING_ANDX_SHARED_LOCK) 726 if(lockType & LOCKING_ANDX_SHARED_LOCK)
696 posix_lock_type = CIFS_RDLCK; 727 posix_lock_type = CIFS_RDLCK;
@@ -699,18 +730,47 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
699 730
700 if(numUnlock == 1) 731 if(numUnlock == 1)
701 posix_lock_type = CIFS_UNLCK; 732 posix_lock_type = CIFS_UNLCK;
702 else if(numLock == 0) { 733
703 /* if no lock or unlock then nothing
704 to do since we do not know what it is */
705 FreeXid(xid);
706 return -EOPNOTSUPP;
707 }
708 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, 734 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
709 length, pfLock, 735 length, pfLock,
710 posix_lock_type, wait_flag); 736 posix_lock_type, wait_flag);
711 } else 737 } else {
712 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, 738 struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;
713 numUnlock, numLock, lockType, wait_flag); 739
740 if (numLock) {
741 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
742 0, numLock, lockType, wait_flag);
743
744 if (rc == 0) {
745 /* For Windows locks we must store them. */
746 rc = store_file_lock(fid, length,
747 pfLock->fl_start, lockType);
748 }
749 } else if (numUnlock) {
750 /* For each stored lock that this unlock overlaps
751 completely, unlock it. */
752 int stored_rc = 0;
753 struct cifsLockInfo *li, *tmp;
754
755 rc = 0;
756 down(&fid->lock_sem);
757 list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
758 if (pfLock->fl_start <= li->offset &&
759 length >= li->length) {
760 stored_rc = CIFSSMBLock(xid, pTcon, netfid,
761 li->length, li->offset,
762 1, 0, li->type, FALSE);
763 if (stored_rc)
764 rc = stored_rc;
765
766 list_del(&li->llist);
767 kfree(li);
768 }
769 }
770 up(&fid->lock_sem);
771 }
772 }
773
714 if (pfLock->fl_flags & FL_POSIX) 774 if (pfLock->fl_flags & FL_POSIX)
715 posix_lock_file_wait(file, pfLock); 775 posix_lock_file_wait(file, pfLock);
716 FreeXid(xid); 776 FreeXid(xid);
@@ -1375,7 +1435,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1375 1435
1376 xid = GetXid(); 1436 xid = GetXid();
1377 1437
1378 cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 1438 cFYI(1, ("Sync file - name: %s datasync: 0x%x",
1379 dentry->d_name.name, datasync)); 1439 dentry->d_name.name, datasync));
1380 1440
1381 rc = filemap_fdatawrite(inode->i_mapping); 1441 rc = filemap_fdatawrite(inode->i_mapping);
@@ -1404,7 +1464,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1404/* fill in rpages then 1464/* fill in rpages then
1405 result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ 1465 result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1406 1466
1407/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index)); 1467/* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index));
1408 1468
1409#if 0 1469#if 0
1410 if (rc < 0) 1470 if (rc < 0)
@@ -1836,7 +1896,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
1836 if (rc < 0) 1896 if (rc < 0)
1837 goto io_error; 1897 goto io_error;
1838 else 1898 else
1839 cFYI(1, ("Bytes read %d ",rc)); 1899 cFYI(1, ("Bytes read %d",rc));
1840 1900
1841 file->f_dentry->d_inode->i_atime = 1901 file->f_dentry->d_inode->i_atime =
1842 current_fs_time(file->f_dentry->d_inode->i_sb); 1902 current_fs_time(file->f_dentry->d_inode->i_sb);
@@ -1946,7 +2006,7 @@ static int cifs_prepare_write(struct file *file, struct page *page,
1946 return 0; 2006 return 0;
1947} 2007}
1948 2008
1949struct address_space_operations cifs_addr_ops = { 2009const struct address_space_operations cifs_addr_ops = {
1950 .readpage = cifs_readpage, 2010 .readpage = cifs_readpage,
1951 .readpages = cifs_readpages, 2011 .readpages = cifs_readpages,
1952 .writepage = cifs_writepage, 2012 .writepage = cifs_writepage,
@@ -1957,3 +2017,19 @@ struct address_space_operations cifs_addr_ops = {
1957 /* .sync_page = cifs_sync_page, */ 2017 /* .sync_page = cifs_sync_page, */
1958 /* .direct_IO = */ 2018 /* .direct_IO = */
1959}; 2019};
2020
2021/*
2022 * cifs_readpages requires the server to support a buffer large enough to
2023 * contain the header plus one complete page of data. Otherwise, we need
2024 * to leave cifs_readpages out of the address space operations.
2025 */
2026const struct address_space_operations cifs_addr_ops_smallbuf = {
2027 .readpage = cifs_readpage,
2028 .writepage = cifs_writepage,
2029 .writepages = cifs_writepages,
2030 .prepare_write = cifs_prepare_write,
2031 .commit_write = cifs_commit_write,
2032 .set_page_dirty = __set_page_dirty_nobuffers,
2033 /* .sync_page = cifs_sync_page, */
2034 /* .direct_IO = */
2035};