diff options
author | Christoph Hellwig <hch@infradead.org> | 2008-02-25 15:25:21 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-02-25 15:25:21 -0500 |
commit | 75f12983d9949fef67ecc133ef4727d93d42b25a (patch) | |
tree | 81ebb40589193fd8e6366cda2a64961d1de6e1cb /fs/cifs | |
parent | e086fcea861f82f2086a97e401a15e1ba07e8566 (diff) |
[CIFS] consolidate duplicate code in posix/unix inode handling
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/inode.c | 279 |
1 files changed, 103 insertions, 176 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 1d8aa0385ef7..8c23fb330ea9 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -69,6 +69,90 @@ static void cifs_set_ops(struct inode *inode) | |||
69 | } | 69 | } |
70 | } | 70 | } |
71 | 71 | ||
72 | static void cifs_unix_info_to_inode(struct inode *inode, | ||
73 | FILE_UNIX_BASIC_INFO *info, int force_uid_gid) | ||
74 | { | ||
75 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
76 | struct cifsInodeInfo *cifsInfo = CIFS_I(inode); | ||
77 | __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); | ||
78 | __u64 end_of_file = le64_to_cpu(info->EndOfFile); | ||
79 | |||
80 | inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(info->LastAccessTime)); | ||
81 | inode->i_mtime = | ||
82 | cifs_NTtimeToUnix(le64_to_cpu(info->LastModificationTime)); | ||
83 | inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(info->LastStatusChange)); | ||
84 | inode->i_mode = le64_to_cpu(info->Permissions); | ||
85 | |||
86 | /* | ||
87 | * Since we set the inode type below we need to mask off | ||
88 | * to avoid strange results if bits set above. | ||
89 | */ | ||
90 | inode->i_mode &= ~S_IFMT; | ||
91 | switch (le32_to_cpu(info->Type)) { | ||
92 | case UNIX_FILE: | ||
93 | inode->i_mode |= S_IFREG; | ||
94 | break; | ||
95 | case UNIX_SYMLINK: | ||
96 | inode->i_mode |= S_IFLNK; | ||
97 | break; | ||
98 | case UNIX_DIR: | ||
99 | inode->i_mode |= S_IFDIR; | ||
100 | break; | ||
101 | case UNIX_CHARDEV: | ||
102 | inode->i_mode |= S_IFCHR; | ||
103 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | ||
104 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
105 | break; | ||
106 | case UNIX_BLOCKDEV: | ||
107 | inode->i_mode |= S_IFBLK; | ||
108 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | ||
109 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
110 | break; | ||
111 | case UNIX_FIFO: | ||
112 | inode->i_mode |= S_IFIFO; | ||
113 | break; | ||
114 | case UNIX_SOCKET: | ||
115 | inode->i_mode |= S_IFSOCK; | ||
116 | break; | ||
117 | default: | ||
118 | /* safest to call it a file if we do not know */ | ||
119 | inode->i_mode |= S_IFREG; | ||
120 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) && | ||
125 | !force_uid_gid) | ||
126 | inode->i_uid = cifs_sb->mnt_uid; | ||
127 | else | ||
128 | inode->i_uid = le64_to_cpu(info->Uid); | ||
129 | |||
130 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) && | ||
131 | !force_uid_gid) | ||
132 | inode->i_gid = cifs_sb->mnt_gid; | ||
133 | else | ||
134 | inode->i_gid = le64_to_cpu(info->Gid); | ||
135 | |||
136 | inode->i_nlink = le64_to_cpu(info->Nlinks); | ||
137 | |||
138 | spin_lock(&inode->i_lock); | ||
139 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
140 | /* | ||
141 | * We can not safely change the file size here if the client | ||
142 | * is writing to it due to potential races. | ||
143 | */ | ||
144 | i_size_write(inode, end_of_file); | ||
145 | |||
146 | /* | ||
147 | * i_blocks is not related to (i_size / i_blksize), | ||
148 | * but instead 512 byte (2**9) size is required for | ||
149 | * calculating num blocks. | ||
150 | */ | ||
151 | inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
152 | } | ||
153 | spin_unlock(&inode->i_lock); | ||
154 | } | ||
155 | |||
72 | int cifs_get_inode_info_unix(struct inode **pinode, | 156 | int cifs_get_inode_info_unix(struct inode **pinode, |
73 | const unsigned char *search_path, struct super_block *sb, int xid) | 157 | const unsigned char *search_path, struct super_block *sb, int xid) |
74 | { | 158 | { |
@@ -114,7 +198,6 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
114 | } | 198 | } |
115 | } else { | 199 | } else { |
116 | struct cifsInodeInfo *cifsInfo; | 200 | struct cifsInodeInfo *cifsInfo; |
117 | __u32 type = le32_to_cpu(findData.Type); | ||
118 | __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); | 201 | __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); |
119 | __u64 end_of_file = le64_to_cpu(findData.EndOfFile); | 202 | __u64 end_of_file = le64_to_cpu(findData.EndOfFile); |
120 | 203 | ||
@@ -145,73 +228,8 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
145 | /* this is ok to set on every inode revalidate */ | 228 | /* this is ok to set on every inode revalidate */ |
146 | atomic_set(&cifsInfo->inUse, 1); | 229 | atomic_set(&cifsInfo->inUse, 1); |
147 | 230 | ||
148 | inode->i_atime = | 231 | cifs_unix_info_to_inode(inode, &findData, 0); |
149 | cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime)); | ||
150 | inode->i_mtime = | ||
151 | cifs_NTtimeToUnix(le64_to_cpu | ||
152 | (findData.LastModificationTime)); | ||
153 | inode->i_ctime = | ||
154 | cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange)); | ||
155 | inode->i_mode = le64_to_cpu(findData.Permissions); | ||
156 | /* since we set the inode type below we need to mask off | ||
157 | to avoid strange results if bits set above */ | ||
158 | inode->i_mode &= ~S_IFMT; | ||
159 | if (type == UNIX_FILE) { | ||
160 | inode->i_mode |= S_IFREG; | ||
161 | } else if (type == UNIX_SYMLINK) { | ||
162 | inode->i_mode |= S_IFLNK; | ||
163 | } else if (type == UNIX_DIR) { | ||
164 | inode->i_mode |= S_IFDIR; | ||
165 | } else if (type == UNIX_CHARDEV) { | ||
166 | inode->i_mode |= S_IFCHR; | ||
167 | inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor), | ||
168 | le64_to_cpu(findData.DevMinor) & MINORMASK); | ||
169 | } else if (type == UNIX_BLOCKDEV) { | ||
170 | inode->i_mode |= S_IFBLK; | ||
171 | inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor), | ||
172 | le64_to_cpu(findData.DevMinor) & MINORMASK); | ||
173 | } else if (type == UNIX_FIFO) { | ||
174 | inode->i_mode |= S_IFIFO; | ||
175 | } else if (type == UNIX_SOCKET) { | ||
176 | inode->i_mode |= S_IFSOCK; | ||
177 | } else { | ||
178 | /* safest to call it a file if we do not know */ | ||
179 | inode->i_mode |= S_IFREG; | ||
180 | cFYI(1, ("unknown type %d", type)); | ||
181 | } | ||
182 | |||
183 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) | ||
184 | inode->i_uid = cifs_sb->mnt_uid; | ||
185 | else | ||
186 | inode->i_uid = le64_to_cpu(findData.Uid); | ||
187 | |||
188 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) | ||
189 | inode->i_gid = cifs_sb->mnt_gid; | ||
190 | else | ||
191 | inode->i_gid = le64_to_cpu(findData.Gid); | ||
192 | |||
193 | inode->i_nlink = le64_to_cpu(findData.Nlinks); | ||
194 | |||
195 | spin_lock(&inode->i_lock); | ||
196 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
197 | /* can not safely change the file size here if the | ||
198 | client is writing to it due to potential races */ | ||
199 | i_size_write(inode, end_of_file); | ||
200 | |||
201 | /* blksize needs to be multiple of two. So safer to default to | ||
202 | blksize and blkbits set in superblock so 2**blkbits and blksize | ||
203 | will match rather than setting to: | ||
204 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ | ||
205 | 232 | ||
206 | /* This seems incredibly stupid but it turns out that i_blocks | ||
207 | is not related to (i_size / i_blksize), instead 512 byte size | ||
208 | is required for calculating num blocks */ | ||
209 | |||
210 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | ||
211 | /* for this calculation */ | ||
212 | inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
213 | } | ||
214 | spin_unlock(&inode->i_lock); | ||
215 | 233 | ||
216 | if (num_of_bytes < end_of_file) | 234 | if (num_of_bytes < end_of_file) |
217 | cFYI(1, ("allocation size less than end of file")); | 235 | cFYI(1, ("allocation size less than end of file")); |
@@ -774,15 +792,10 @@ psx_del_no_retry: | |||
774 | static void posix_fill_in_inode(struct inode *tmp_inode, | 792 | static void posix_fill_in_inode(struct inode *tmp_inode, |
775 | FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode) | 793 | FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode) |
776 | { | 794 | { |
795 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
777 | loff_t local_size; | 796 | loff_t local_size; |
778 | struct timespec local_mtime; | 797 | struct timespec local_mtime; |
779 | 798 | ||
780 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
781 | struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); | ||
782 | |||
783 | __u32 type = le32_to_cpu(pData->Type); | ||
784 | __u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes); | ||
785 | __u64 end_of_file = le64_to_cpu(pData->EndOfFile); | ||
786 | cifsInfo->time = jiffies; | 799 | cifsInfo->time = jiffies; |
787 | atomic_inc(&cifsInfo->inUse); | 800 | atomic_inc(&cifsInfo->inUse); |
788 | 801 | ||
@@ -790,113 +803,27 @@ static void posix_fill_in_inode(struct inode *tmp_inode, | |||
790 | local_mtime = tmp_inode->i_mtime; | 803 | local_mtime = tmp_inode->i_mtime; |
791 | local_size = tmp_inode->i_size; | 804 | local_size = tmp_inode->i_size; |
792 | 805 | ||
793 | tmp_inode->i_atime = | 806 | cifs_unix_info_to_inode(tmp_inode, pData, 1); |
794 | cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime)); | 807 | cifs_set_ops(tmp_inode); |
795 | tmp_inode->i_mtime = | ||
796 | cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime)); | ||
797 | tmp_inode->i_ctime = | ||
798 | cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange)); | ||
799 | |||
800 | tmp_inode->i_mode = le64_to_cpu(pData->Permissions); | ||
801 | /* since we set the inode type below we need to mask off type | ||
802 | to avoid strange results if bits above were corrupt */ | ||
803 | tmp_inode->i_mode &= ~S_IFMT; | ||
804 | if (type == UNIX_FILE) { | ||
805 | *pobject_type = DT_REG; | ||
806 | tmp_inode->i_mode |= S_IFREG; | ||
807 | } else if (type == UNIX_SYMLINK) { | ||
808 | *pobject_type = DT_LNK; | ||
809 | tmp_inode->i_mode |= S_IFLNK; | ||
810 | } else if (type == UNIX_DIR) { | ||
811 | *pobject_type = DT_DIR; | ||
812 | tmp_inode->i_mode |= S_IFDIR; | ||
813 | } else if (type == UNIX_CHARDEV) { | ||
814 | *pobject_type = DT_CHR; | ||
815 | tmp_inode->i_mode |= S_IFCHR; | ||
816 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor), | ||
817 | le64_to_cpu(pData->DevMinor) & MINORMASK); | ||
818 | } else if (type == UNIX_BLOCKDEV) { | ||
819 | *pobject_type = DT_BLK; | ||
820 | tmp_inode->i_mode |= S_IFBLK; | ||
821 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor), | ||
822 | le64_to_cpu(pData->DevMinor) & MINORMASK); | ||
823 | } else if (type == UNIX_FIFO) { | ||
824 | *pobject_type = DT_FIFO; | ||
825 | tmp_inode->i_mode |= S_IFIFO; | ||
826 | } else if (type == UNIX_SOCKET) { | ||
827 | *pobject_type = DT_SOCK; | ||
828 | tmp_inode->i_mode |= S_IFSOCK; | ||
829 | } else { | ||
830 | /* safest to just call it a file */ | ||
831 | *pobject_type = DT_REG; | ||
832 | tmp_inode->i_mode |= S_IFREG; | ||
833 | cFYI(1, ("unknown inode type %d", type)); | ||
834 | } | ||
835 | |||
836 | cFYI(DBG2, ("object type: %d", type)); | ||
837 | tmp_inode->i_uid = le64_to_cpu(pData->Uid); | ||
838 | tmp_inode->i_gid = le64_to_cpu(pData->Gid); | ||
839 | tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks); | ||
840 | 808 | ||
841 | spin_lock(&tmp_inode->i_lock); | 809 | if (!S_ISREG(tmp_inode->i_mode)) |
842 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | 810 | return; |
843 | /* can not safely change the file size here if the | ||
844 | client is writing to it due to potential races */ | ||
845 | i_size_write(tmp_inode, end_of_file); | ||
846 | |||
847 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | ||
848 | /* for this calculation, not the real blocksize */ | ||
849 | tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
850 | } | ||
851 | spin_unlock(&tmp_inode->i_lock); | ||
852 | |||
853 | if (S_ISREG(tmp_inode->i_mode)) { | ||
854 | cFYI(1, ("File inode")); | ||
855 | tmp_inode->i_op = &cifs_file_inode_ops; | ||
856 | |||
857 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||
858 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
859 | tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; | ||
860 | else | ||
861 | tmp_inode->i_fop = &cifs_file_direct_ops; | ||
862 | 811 | ||
863 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 812 | /* |
864 | tmp_inode->i_fop = &cifs_file_nobrl_ops; | 813 | * No sense invalidating pages for new inode |
865 | else | 814 | * since we we have not started caching |
866 | tmp_inode->i_fop = &cifs_file_ops; | 815 | * readahead file data yet. |
867 | 816 | */ | |
868 | if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | 817 | if (isNewInode) |
869 | (cifs_sb->tcon->ses->server->maxBuf < | 818 | return; |
870 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) | ||
871 | tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
872 | else | ||
873 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | ||
874 | |||
875 | if (isNewInode) | ||
876 | return; /* No sense invalidating pages for new inode | ||
877 | since we we have not started caching | ||
878 | readahead file data yet */ | ||
879 | 819 | ||
880 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | 820 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && |
881 | (local_size == tmp_inode->i_size)) { | 821 | (local_size == tmp_inode->i_size)) { |
882 | cFYI(1, ("inode exists but unchanged")); | 822 | cFYI(1, ("inode exists but unchanged")); |
883 | } else { | ||
884 | /* file may have changed on server */ | ||
885 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
886 | invalidate_remote_inode(tmp_inode); | ||
887 | } | ||
888 | } else if (S_ISDIR(tmp_inode->i_mode)) { | ||
889 | cFYI(1, ("Directory inode")); | ||
890 | tmp_inode->i_op = &cifs_dir_inode_ops; | ||
891 | tmp_inode->i_fop = &cifs_dir_ops; | ||
892 | } else if (S_ISLNK(tmp_inode->i_mode)) { | ||
893 | cFYI(1, ("Symbolic Link inode")); | ||
894 | tmp_inode->i_op = &cifs_symlink_inode_ops; | ||
895 | /* tmp_inode->i_fop = *//* do not need to set to anything */ | ||
896 | } else { | 823 | } else { |
897 | cFYI(1, ("Special inode")); | 824 | /* file may have changed on server */ |
898 | init_special_inode(tmp_inode, tmp_inode->i_mode, | 825 | cFYI(1, ("invalidate inode, readdir detected change")); |
899 | tmp_inode->i_rdev); | 826 | invalidate_remote_inode(tmp_inode); |
900 | } | 827 | } |
901 | } | 828 | } |
902 | 829 | ||