aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2007-04-23 18:07:35 -0400
committerSteve French <sfrench@us.ibm.com>2007-04-23 18:07:35 -0400
commit2dd29d3133ad4c7926ea03b8431e604373c4ad65 (patch)
tree67865fc39bc4095fee16b6a6329c778360d51945 /fs/cifs/inode.c
parent5268df2ead6def933ace27ab4d46f67d2989b905 (diff)
[CIFS] New CIFS POSIX mkdir performance improvement
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c184
1 files changed, 181 insertions, 3 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index eeea33752e68..9b7e0dbdd826 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/inode.c 2 * fs/cifs/inode.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2005 4 * Copyright (C) International Business Machines Corp., 2002,2007
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -734,6 +734,133 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
734 return rc; 734 return rc;
735} 735}
736 736
737static void posix_fill_in_inode(struct inode *tmp_inode,
738 FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode)
739{
740 loff_t local_size;
741 struct timespec local_mtime;
742
743 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
744 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
745
746 __u32 type = le32_to_cpu(pData->Type);
747 __u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes);
748 __u64 end_of_file = le64_to_cpu(pData->EndOfFile);
749 cifsInfo->time = jiffies;
750 atomic_inc(&cifsInfo->inUse);
751
752 /* save mtime and size */
753 local_mtime = tmp_inode->i_mtime;
754 local_size = tmp_inode->i_size;
755
756 tmp_inode->i_atime =
757 cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime));
758 tmp_inode->i_mtime =
759 cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime));
760 tmp_inode->i_ctime =
761 cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange));
762
763 tmp_inode->i_mode = le64_to_cpu(pData->Permissions);
764 /* since we set the inode type below we need to mask off type
765 to avoid strange results if bits above were corrupt */
766 tmp_inode->i_mode &= ~S_IFMT;
767 if (type == UNIX_FILE) {
768 *pobject_type = DT_REG;
769 tmp_inode->i_mode |= S_IFREG;
770 } else if (type == UNIX_SYMLINK) {
771 *pobject_type = DT_LNK;
772 tmp_inode->i_mode |= S_IFLNK;
773 } else if (type == UNIX_DIR) {
774 *pobject_type = DT_DIR;
775 tmp_inode->i_mode |= S_IFDIR;
776 } else if (type == UNIX_CHARDEV) {
777 *pobject_type = DT_CHR;
778 tmp_inode->i_mode |= S_IFCHR;
779 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
780 le64_to_cpu(pData->DevMinor) & MINORMASK);
781 } else if (type == UNIX_BLOCKDEV) {
782 *pobject_type = DT_BLK;
783 tmp_inode->i_mode |= S_IFBLK;
784 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
785 le64_to_cpu(pData->DevMinor) & MINORMASK);
786 } else if (type == UNIX_FIFO) {
787 *pobject_type = DT_FIFO;
788 tmp_inode->i_mode |= S_IFIFO;
789 } else if (type == UNIX_SOCKET) {
790 *pobject_type = DT_SOCK;
791 tmp_inode->i_mode |= S_IFSOCK;
792 } else {
793 /* safest to just call it a file */
794 *pobject_type = DT_REG;
795 tmp_inode->i_mode |= S_IFREG;
796 cFYI(1,("unknown inode type %d",type));
797 }
798
799 tmp_inode->i_uid = le64_to_cpu(pData->Uid);
800 tmp_inode->i_gid = le64_to_cpu(pData->Gid);
801 tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks);
802
803 spin_lock(&tmp_inode->i_lock);
804 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
805 /* can not safely change the file size here if the
806 client is writing to it due to potential races */
807 i_size_write(tmp_inode, end_of_file);
808
809 /* 512 bytes (2**9) is the fake blocksize that must be used */
810 /* for this calculation, not the real blocksize */
811 tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
812 }
813 spin_unlock(&tmp_inode->i_lock);
814
815 if (S_ISREG(tmp_inode->i_mode)) {
816 cFYI(1, ("File inode"));
817 tmp_inode->i_op = &cifs_file_inode_ops;
818
819 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
820 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
821 tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
822 else
823 tmp_inode->i_fop = &cifs_file_direct_ops;
824
825 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
826 tmp_inode->i_fop = &cifs_file_nobrl_ops;
827 else
828 tmp_inode->i_fop = &cifs_file_ops;
829
830 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
831 (cifs_sb->tcon->ses->server->maxBuf <
832 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
833 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
834 else
835 tmp_inode->i_data.a_ops = &cifs_addr_ops;
836
837 if(isNewInode)
838 return; /* No sense invalidating pages for new inode since we
839 have not started caching readahead file data yet */
840
841 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
842 (local_size == tmp_inode->i_size)) {
843 cFYI(1, ("inode exists but unchanged"));
844 } else {
845 /* file may have changed on server */
846 cFYI(1, ("invalidate inode, readdir detected change"));
847 invalidate_remote_inode(tmp_inode);
848 }
849 } else if (S_ISDIR(tmp_inode->i_mode)) {
850 cFYI(1, ("Directory inode"));
851 tmp_inode->i_op = &cifs_dir_inode_ops;
852 tmp_inode->i_fop = &cifs_dir_ops;
853 } else if (S_ISLNK(tmp_inode->i_mode)) {
854 cFYI(1, ("Symbolic Link inode"));
855 tmp_inode->i_op = &cifs_symlink_inode_ops;
856/* tmp_inode->i_fop = *//* do not need to set to anything */
857 } else {
858 cFYI(1, ("Special inode"));
859 init_special_inode(tmp_inode, tmp_inode->i_mode,
860 tmp_inode->i_rdev);
861 }
862}
863
737int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) 864int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
738{ 865{
739 int rc = 0; 866 int rc = 0;
@@ -755,6 +882,53 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
755 FreeXid(xid); 882 FreeXid(xid);
756 return -ENOMEM; 883 return -ENOMEM;
757 } 884 }
885
886 if((pTcon->ses->capabilities & CAP_UNIX) &&
887 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
888 le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
889 u32 oplock = 0;
890 FILE_UNIX_BASIC_INFO * pInfo =
891 kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
892 if(pInfo == NULL) {
893 rc = -ENOMEM;
894 goto mkdir_out;
895 }
896
897 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
898 mode, NULL /* netfid */, pInfo, &oplock,
899 full_path, cifs_sb->local_nls,
900 cifs_sb->mnt_cifs_flags &
901 CIFS_MOUNT_MAP_SPECIAL_CHR);
902 if (rc) {
903 cFYI(1, ("posix mkdir returned 0x%x", rc));
904 d_drop(direntry);
905 } else {
906 if (pInfo->Type == -1) /* no return info - go query */
907 goto mkdir_get_info;
908/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */
909 inc_nlink(inode);
910 if (pTcon->nocase)
911 direntry->d_op = &cifs_ci_dentry_ops;
912 else
913 direntry->d_op = &cifs_dentry_ops;
914 d_instantiate(direntry, newinode);
915 if (direntry->d_inode) {
916 int obj_type;
917 direntry->d_inode->i_nlink = 2;
918 /* already checked in POSIXCreate whether
919 frame was long enough */
920 posix_fill_in_inode(direntry->d_inode,
921 pInfo, &obj_type, 1 /* NewInode */);
922 /* could double check that we actually
923 * created what we thought we did ie
924 * a directory
925 */
926 }
927 }
928 kfree(pInfo);
929 goto mkdir_out;
930 }
931
758 /* BB add setting the equivalent of mode via CreateX w/ACLs */ 932 /* BB add setting the equivalent of mode via CreateX w/ACLs */
759 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, 933 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
760 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 934 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -762,6 +936,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
762 cFYI(1, ("cifs_mkdir returned 0x%x", rc)); 936 cFYI(1, ("cifs_mkdir returned 0x%x", rc));
763 d_drop(direntry); 937 d_drop(direntry);
764 } else { 938 } else {
939mkdir_get_info:
765 inc_nlink(inode); 940 inc_nlink(inode);
766 if (pTcon->ses->capabilities & CAP_UNIX) 941 if (pTcon->ses->capabilities & CAP_UNIX)
767 rc = cifs_get_inode_info_unix(&newinode, full_path, 942 rc = cifs_get_inode_info_unix(&newinode, full_path,
@@ -775,8 +950,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
775 else 950 else
776 direntry->d_op = &cifs_dentry_ops; 951 direntry->d_op = &cifs_dentry_ops;
777 d_instantiate(direntry, newinode); 952 d_instantiate(direntry, newinode);
778 if (direntry->d_inode) 953 /* setting nlink not necessary except in cases where we
779 direntry->d_inode->i_nlink = 2; 954 * failed to get it from the server or was set bogus */
955 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
956 direntry->d_inode->i_nlink = 2;
780 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) 957 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
781 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 958 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
782 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 959 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
@@ -812,6 +989,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
812 } 989 }
813 } 990 }
814 } 991 }
992mkdir_out:
815 kfree(full_path); 993 kfree(full_path);
816 FreeXid(xid); 994 FreeXid(xid);
817 return rc; 995 return rc;