aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/readdir.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2009-07-09 01:46:37 -0400
committerSteve French <sfrench@us.ibm.com>2009-07-09 19:05:48 -0400
commit0b8f18e358384a52c1ed7fa7129c08e7eaf86bb6 (patch)
treeba5292a38d8910c6b3a3303a3c7f88491e1708af /fs/cifs/readdir.c
parentb77863bfa153e886f9f8faf1a791ba57a36efed0 (diff)
cifs: convert cifs_get_inode_info and non-posix readdir to use cifs_iget
cifs: convert cifs_get_inode_info and non-posix readdir to use cifs_iget Rather than allocating an inode and filling it out, have cifs_get_inode_info fill out a cifs_fattr and call cifs_iget. This means a pretty hefty reorganization of cifs_get_inode_info. For the readdir codepath, add a couple of new functions for filling out cifs_fattr's from different FindFile response infolevels. Finally, remove cifs_new_inode since there are no more callers. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/readdir.c')
-rw-r--r--fs/cifs/readdir.c350
1 files changed, 83 insertions, 267 deletions
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 231aa6953f83..f823a4a208a7 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -112,239 +112,74 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
112 return dentry; 112 return dentry;
113} 113}
114 114
115/* Returns 1 if new inode created, 2 if both dentry and inode were */ 115static void
116/* Might check in the future if inode number changed so we can rehash inode */ 116cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
117static int
118construct_dentry(struct qstr *qstring, struct file *file,
119 struct inode **ptmp_inode, struct dentry **pnew_dentry,
120 __u64 *inum)
121{ 117{
122 struct dentry *tmp_dentry = NULL; 118 fattr->cf_uid = cifs_sb->mnt_uid;
123 struct super_block *sb = file->f_path.dentry->d_sb; 119 fattr->cf_gid = cifs_sb->mnt_gid;
124 int rc = 0;
125 120
126 cFYI(1, ("For %s", qstring->name)); 121 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
127 122 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
128 tmp_dentry = d_lookup(file->f_path.dentry, qstring); 123 fattr->cf_dtype = DT_DIR;
129 if (tmp_dentry) {
130 /* BB: overwrite old name? i.e. tmp_dentry->d_name and
131 * tmp_dentry->d_name.len??
132 */
133 cFYI(0, ("existing dentry with inode 0x%p",
134 tmp_dentry->d_inode));
135 *ptmp_inode = tmp_dentry->d_inode;
136 if (*ptmp_inode == NULL) {
137 *ptmp_inode = cifs_new_inode(sb, inum);
138 if (*ptmp_inode == NULL)
139 return rc;
140 rc = 1;
141 }
142 } else { 124 } else {
143 tmp_dentry = d_alloc(file->f_path.dentry, qstring); 125 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
144 if (tmp_dentry == NULL) { 126 fattr->cf_dtype = DT_REG;
145 cERROR(1, ("Failed allocating dentry"));
146 *ptmp_inode = NULL;
147 return rc;
148 }
149
150 if (CIFS_SB(sb)->tcon->nocase)
151 tmp_dentry->d_op = &cifs_ci_dentry_ops;
152 else
153 tmp_dentry->d_op = &cifs_dentry_ops;
154
155 *ptmp_inode = cifs_new_inode(sb, inum);
156 if (*ptmp_inode == NULL)
157 return rc;
158 rc = 2;
159 }
160
161 tmp_dentry->d_time = jiffies;
162 *pnew_dentry = tmp_dentry;
163 return rc;
164}
165
166static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
167 char *buf, unsigned int *pobject_type, int isNewInode)
168{
169 loff_t local_size;
170 struct timespec local_mtime;
171
172 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
173 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
174 __u32 attr;
175 __u64 allocation_size;
176 __u64 end_of_file;
177 umode_t default_mode;
178
179 /* save mtime and size */
180 local_mtime = tmp_inode->i_mtime;
181 local_size = tmp_inode->i_size;
182
183 if (new_buf_type) {
184 FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;
185
186 attr = le32_to_cpu(pfindData->ExtFileAttributes);
187 allocation_size = le64_to_cpu(pfindData->AllocationSize);
188 end_of_file = le64_to_cpu(pfindData->EndOfFile);
189 tmp_inode->i_atime =
190 cifs_NTtimeToUnix(pfindData->LastAccessTime);
191 tmp_inode->i_mtime =
192 cifs_NTtimeToUnix(pfindData->LastWriteTime);
193 tmp_inode->i_ctime =
194 cifs_NTtimeToUnix(pfindData->ChangeTime);
195 } else { /* legacy, OS2 and DOS style */
196 int offset = cifs_sb->tcon->ses->server->timeAdj;
197 FIND_FILE_STANDARD_INFO *pfindData =
198 (FIND_FILE_STANDARD_INFO *)buf;
199
200 tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate,
201 pfindData->LastWriteTime,
202 offset);
203 tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate,
204 pfindData->LastAccessTime,
205 offset);
206 tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate,
207 pfindData->LastWriteTime,
208 offset);
209 attr = le16_to_cpu(pfindData->Attributes);
210 allocation_size = le32_to_cpu(pfindData->AllocationSize);
211 end_of_file = le32_to_cpu(pfindData->DataSize);
212 }
213
214 /* Linux can not store file creation time unfortunately so ignore it */
215
216 cifsInfo->cifsAttrs = attr;
217#ifdef CONFIG_CIFS_EXPERIMENTAL
218 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
219 /* get more accurate mode via ACL - so force inode refresh */
220 cifsInfo->time = 0;
221 } else
222#endif /* CONFIG_CIFS_EXPERIMENTAL */
223 cifsInfo->time = jiffies;
224
225 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
226 /* 2767 perms - indicate mandatory locking */
227 /* BB fill in uid and gid here? with help from winbind?
228 or retrieve from NTFS stream extended attribute */
229 if (atomic_read(&cifsInfo->inUse) == 0) {
230 tmp_inode->i_uid = cifs_sb->mnt_uid;
231 tmp_inode->i_gid = cifs_sb->mnt_gid;
232 } 127 }
233 128
234 if (attr & ATTR_DIRECTORY) 129 if (fattr->cf_cifsattrs & ATTR_READONLY)
235 default_mode = cifs_sb->mnt_dir_mode; 130 fattr->cf_mode &= ~S_IWUGO;
236 else
237 default_mode = cifs_sb->mnt_file_mode;
238
239 /* set initial permissions */
240 if ((atomic_read(&cifsInfo->inUse) == 0) ||
241 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
242 tmp_inode->i_mode = default_mode;
243 else {
244 /* just reenable write bits if !ATTR_READONLY */
245 if ((tmp_inode->i_mode & S_IWUGO) == 0 &&
246 (attr & ATTR_READONLY) == 0)
247 tmp_inode->i_mode |= (S_IWUGO & default_mode);
248
249 tmp_inode->i_mode &= ~S_IFMT;
250 }
251
252 /* clear write bits if ATTR_READONLY is set */
253 if (attr & ATTR_READONLY)
254 tmp_inode->i_mode &= ~S_IWUGO;
255 131
256 /* set inode type */ 132 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
257 if ((attr & ATTR_SYSTEM) && 133 fattr->cf_cifsattrs & ATTR_SYSTEM) {
258 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { 134 if (fattr->cf_eof == 0) {
259 if (end_of_file == 0) { 135 fattr->cf_mode &= ~S_IFMT;
260 tmp_inode->i_mode |= S_IFIFO; 136 fattr->cf_mode |= S_IFIFO;
261 *pobject_type = DT_FIFO; 137 fattr->cf_dtype = DT_FIFO;
262 } else { 138 } else {
263 /* 139 /*
264 * trying to get the type can be slow, so just call 140 * trying to get the type and mode via SFU can be slow,
265 * this a regular file for now, and mark for reval 141 * so just call those regular files for now, and mark
142 * for reval
266 */ 143 */
267 tmp_inode->i_mode |= S_IFREG; 144 fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
268 *pobject_type = DT_REG;
269 cifsInfo->time = 0;
270 }
271 } else {
272 if (attr & ATTR_DIRECTORY) {
273 tmp_inode->i_mode |= S_IFDIR;
274 *pobject_type = DT_DIR;
275 } else {
276 tmp_inode->i_mode |= S_IFREG;
277 *pobject_type = DT_REG;
278 } 145 }
279 } 146 }
147}
280 148
281 /* can not fill in nlink here as in qpathinfo version and Unx search */ 149void
282 if (atomic_read(&cifsInfo->inUse) == 0) 150cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
283 atomic_set(&cifsInfo->inUse, 1); 151 struct cifs_sb_info *cifs_sb)
152{
153 memset(fattr, 0, sizeof(*fattr));
154 fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
155 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
156 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
157 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
158 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
159 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
160
161 cifs_fill_common_info(fattr, cifs_sb);
162}
284 163
285 cifsInfo->server_eof = end_of_file; 164void
286 spin_lock(&tmp_inode->i_lock); 165cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
287 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 166 struct cifs_sb_info *cifs_sb)
288 /* can not safely change the file size here if the 167{
289 client is writing to it due to potential races */ 168 int offset = cifs_sb->tcon->ses->server->timeAdj;
290 i_size_write(tmp_inode, end_of_file);
291 169
292 /* 512 bytes (2**9) is the fake blocksize that must be used */ 170 memset(fattr, 0, sizeof(*fattr));
293 /* for this calculation, even though the reported blocksize is larger */ 171 fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
294 tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9; 172 info->LastAccessTime, offset);
295 } 173 fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate,
296 spin_unlock(&tmp_inode->i_lock); 174 info->LastWriteTime, offset);
297 175 fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate,
298 if (allocation_size < end_of_file) 176 info->LastWriteTime, offset);
299 cFYI(1, ("May be sparse file, allocation less than file size")); 177
300 cFYI(1, ("File Size %ld and blocks %llu", 178 fattr->cf_cifsattrs = le16_to_cpu(info->Attributes);
301 (unsigned long)tmp_inode->i_size, 179 fattr->cf_bytes = le32_to_cpu(info->AllocationSize);
302 (unsigned long long)tmp_inode->i_blocks)); 180 fattr->cf_eof = le32_to_cpu(info->DataSize);
303 if (S_ISREG(tmp_inode->i_mode)) { 181
304 cFYI(1, ("File inode")); 182 cifs_fill_common_info(fattr, cifs_sb);
305 tmp_inode->i_op = &cifs_file_inode_ops;
306 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
307 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
308 tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
309 else
310 tmp_inode->i_fop = &cifs_file_direct_ops;
311 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
312 tmp_inode->i_fop = &cifs_file_nobrl_ops;
313 else
314 tmp_inode->i_fop = &cifs_file_ops;
315
316 if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
317 (cifs_sb->tcon->ses->server->maxBuf <
318 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
319 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
320 else
321 tmp_inode->i_data.a_ops = &cifs_addr_ops;
322
323 if (isNewInode)
324 return; /* No sense invalidating pages for new inode
325 since have not started caching readahead file
326 data yet */
327
328 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
329 (local_size == tmp_inode->i_size)) {
330 cFYI(1, ("inode exists but unchanged"));
331 } else {
332 /* file may have changed on server */
333 cFYI(1, ("invalidate inode, readdir detected change"));
334 invalidate_remote_inode(tmp_inode);
335 }
336 } else if (S_ISDIR(tmp_inode->i_mode)) {
337 cFYI(1, ("Directory inode"));
338 tmp_inode->i_op = &cifs_dir_inode_ops;
339 tmp_inode->i_fop = &cifs_dir_ops;
340 } else if (S_ISLNK(tmp_inode->i_mode)) {
341 cFYI(1, ("Symbolic Link inode"));
342 tmp_inode->i_op = &cifs_symlink_inode_ops;
343 } else {
344 cFYI(1, ("Init special inode"));
345 init_special_inode(tmp_inode, tmp_inode->i_mode,
346 tmp_inode->i_rdev);
347 }
348} 183}
349 184
350/* BB eventually need to add the following helper function to 185/* BB eventually need to add the following helper function to
@@ -846,11 +681,10 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
846 int rc = 0; 681 int rc = 0;
847 struct qstr qstring; 682 struct qstr qstring;
848 struct cifsFileInfo *pCifsF; 683 struct cifsFileInfo *pCifsF;
849 unsigned int obj_type; 684 u64 inum;
850 __u64 inum;
851 ino_t ino; 685 ino_t ino;
686 struct super_block *sb;
852 struct cifs_sb_info *cifs_sb; 687 struct cifs_sb_info *cifs_sb;
853 struct inode *tmp_inode;
854 struct dentry *tmp_dentry; 688 struct dentry *tmp_dentry;
855 struct cifs_fattr fattr; 689 struct cifs_fattr fattr;
856 690
@@ -870,71 +704,53 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
870 if (rc != 0) 704 if (rc != 0)
871 return 0; 705 return 0;
872 706
873 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 707 sb = file->f_path.dentry->d_sb;
708 cifs_sb = CIFS_SB(sb);
874 709
875 qstring.name = scratch_buf; 710 qstring.name = scratch_buf;
876 rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, 711 rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
877 pCifsF->srch_inf.info_level, 712 pCifsF->srch_inf.info_level,
878 pCifsF->srch_inf.unicode, cifs_sb, 713 pCifsF->srch_inf.unicode, cifs_sb,
879 max_len, 714 max_len, &inum /* returned */);
880 &inum /* returned */);
881 715
882 if (rc) 716 if (rc)
883 return rc; 717 return rc;
884 718
885 /* only these two infolevels return valid inode numbers */ 719 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
886 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
887 cifs_unix_basic_to_fattr(&fattr, 720 cifs_unix_basic_to_fattr(&fattr,
888 &((FILE_UNIX_INFO *) pfindEntry)->basic, 721 &((FILE_UNIX_INFO *) pfindEntry)->basic,
889 cifs_sb); 722 cifs_sb);
890 tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, 723 else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
891 &fattr); 724 cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)
892 obj_type = fattr.cf_dtype; 725 pfindEntry, cifs_sb);
893 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); 726 else
894 } else { 727 cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
895 if (pCifsF->srch_inf.info_level == 728 pfindEntry, cifs_sb);
896 SMB_FIND_FILE_ID_FULL_DIR_INFO)
897 rc = construct_dentry(&qstring, file, &tmp_inode,
898 &tmp_dentry, &inum);
899 else
900 rc = construct_dentry(&qstring, file, &tmp_inode,
901 &tmp_dentry, NULL);
902
903 if ((tmp_inode == NULL) || (tmp_dentry == NULL)) {
904 rc = -ENOMEM;
905 goto out;
906 }
907
908 /* we pass in rc below, indicating whether it is a new inode,
909 * so we can figure out whether to invalidate the inode cached
910 * data if the file has changed
911 */
912 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
913 fill_in_inode(tmp_inode, 0, pfindEntry, &obj_type, rc);
914 else
915 fill_in_inode(tmp_inode, 1, pfindEntry, &obj_type, rc);
916 729
917 /* new inode - needs to be tied to dentry */ 730 /* FIXME: make _to_fattr functions fill this out */
918 if (rc) { 731 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO)
919 d_instantiate(tmp_dentry, tmp_inode); 732 fattr.cf_uniqueid = inum;
920 if (rc == 2) 733 else
921 d_rehash(tmp_dentry); 734 fattr.cf_uniqueid = iunique(sb, ROOT_I);
922 }
923 735
924 ino = cifs_uniqueid_to_ino_t(tmp_inode->i_ino); 736 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
925 } 737 tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);
926 738
927 rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, 739 rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
928 ino, obj_type); 740 ino, fattr.cf_dtype);
741
742 /*
743 * we can not return filldir errors to the caller since they are
744 * "normal" when the stat blocksize is too small - we return remapped
745 * error instead
746 *
747 * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above
748 * case already. Why should we be clobbering other errors from it?
749 */
929 if (rc) { 750 if (rc) {
930 cFYI(1, ("filldir rc = %d", rc)); 751 cFYI(1, ("filldir rc = %d", rc));
931 /* we can not return filldir errors to the caller
932 since they are "normal" when the stat blocksize
933 is too small - we return remapped error instead */
934 rc = -EOVERFLOW; 752 rc = -EOVERFLOW;
935 } 753 }
936
937out:
938 dput(tmp_dentry); 754 dput(tmp_dentry);
939 return rc; 755 return rc;
940} 756}