diff options
author | Jeff Layton <jlayton@redhat.com> | 2009-06-25 00:56:52 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2009-07-01 17:26:42 -0400 |
commit | cc0bad7552308e8905d6ea56e6b7811fa67e716d (patch) | |
tree | c02a91f13a502f444330b91b36ab12f55f352268 /fs | |
parent | d960eea974f5e500c0dcb95a934239cc1f481cfd (diff) |
cifs: add new cifs_iget function and convert unix codepath to use it
cifs: add new cifs_iget function and convert unix codepath to use it
In order to unify some codepaths, introduce a common cifs_fattr struct
for storing inode attributes. The different codepaths (unix, legacy,
normal, etc...) can fill out this struct with inode info. It can then be
passed as an arg to a common set of routines to get and update inodes.
Add a new cifs_iget function that uses iget5_locked to identify inodes.
This will compare inodes based on the uniqueid value in a cifs_fattr
struct.
Rather than filling out an already-created inode, have
cifs_get_inode_info_unix instead fill out cifs_fattr and hand that off
to cifs_iget. cifs_iget can then properly look for hardlinked inodes.
On the readdir side, add a new cifs_readdir_lookup function that spawns
populated dentries. Redefine FILE_UNIX_INFO so that it's basically a
FILE_UNIX_BASIC_INFO that has a few fields wrapped around it. This
allows us to more easily use the same function for filling out the fattr
as the non-readdir codepath.
With this, we should then have proper hardlink detection and can
eventually get rid of some nasty CIFS-specific hacks for handing them.
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')
-rw-r--r-- | fs/cifs/cifsfs.h | 13 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 25 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 14 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 9 | ||||
-rw-r--r-- | fs/cifs/dir.c | 22 | ||||
-rw-r--r-- | fs/cifs/inode.c | 380 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 253 |
7 files changed, 339 insertions, 377 deletions
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 9570a0e8023f..586df24c9abb 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -24,6 +24,19 @@ | |||
24 | 24 | ||
25 | #define ROOT_I 2 | 25 | #define ROOT_I 2 |
26 | 26 | ||
27 | /* | ||
28 | * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down | ||
29 | * so that it will fit. | ||
30 | */ | ||
31 | static inline ino_t | ||
32 | cifs_uniqueid_to_ino_t(u64 fileid) | ||
33 | { | ||
34 | ino_t ino = (ino_t) fileid; | ||
35 | if (sizeof(ino_t) < sizeof(u64)) | ||
36 | ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8; | ||
37 | return ino; | ||
38 | } | ||
39 | |||
27 | extern struct file_system_type cifs_fs_type; | 40 | extern struct file_system_type cifs_fs_type; |
28 | extern const struct address_space_operations cifs_addr_ops; | 41 | extern const struct address_space_operations cifs_addr_ops; |
29 | extern const struct address_space_operations cifs_addr_ops_smallbuf; | 42 | extern const struct address_space_operations cifs_addr_ops_smallbuf; |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e1225e6ded2f..e6435cba8113 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -371,6 +371,7 @@ struct cifsInodeInfo { | |||
371 | bool oplockPending:1; | 371 | bool oplockPending:1; |
372 | bool delete_pending:1; /* DELETE_ON_CLOSE is set */ | 372 | bool delete_pending:1; /* DELETE_ON_CLOSE is set */ |
373 | u64 server_eof; /* current file size on server */ | 373 | u64 server_eof; /* current file size on server */ |
374 | u64 uniqueid; /* server inode number */ | ||
374 | struct inode vfs_inode; | 375 | struct inode vfs_inode; |
375 | }; | 376 | }; |
376 | 377 | ||
@@ -472,6 +473,30 @@ struct dfs_info3_param { | |||
472 | char *node_name; | 473 | char *node_name; |
473 | }; | 474 | }; |
474 | 475 | ||
476 | /* | ||
477 | * common struct for holding inode info when searching for or updating an | ||
478 | * inode with new info | ||
479 | */ | ||
480 | |||
481 | #define CIFS_FATTR_DFS_REFERRAL 0x1 | ||
482 | |||
483 | struct cifs_fattr { | ||
484 | u32 cf_flags; | ||
485 | u32 cf_cifsattrs; | ||
486 | u64 cf_uniqueid; | ||
487 | u64 cf_eof; | ||
488 | u64 cf_bytes; | ||
489 | uid_t cf_uid; | ||
490 | gid_t cf_gid; | ||
491 | umode_t cf_mode; | ||
492 | dev_t cf_rdev; | ||
493 | unsigned int cf_nlink; | ||
494 | unsigned int cf_dtype; | ||
495 | struct timespec cf_atime; | ||
496 | struct timespec cf_mtime; | ||
497 | struct timespec cf_ctime; | ||
498 | }; | ||
499 | |||
475 | static inline void free_dfs_info_param(struct dfs_info3_param *param) | 500 | static inline void free_dfs_info_param(struct dfs_info3_param *param) |
476 | { | 501 | { |
477 | if (param) { | 502 | if (param) { |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index a785f69dbc9f..2d07f890a842 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -2328,19 +2328,7 @@ struct file_attrib_tag { | |||
2328 | typedef struct { | 2328 | typedef struct { |
2329 | __le32 NextEntryOffset; | 2329 | __le32 NextEntryOffset; |
2330 | __u32 ResumeKey; /* as with FileIndex - no need to convert */ | 2330 | __u32 ResumeKey; /* as with FileIndex - no need to convert */ |
2331 | __le64 EndOfFile; | 2331 | FILE_UNIX_BASIC_INFO basic; |
2332 | __le64 NumOfBytes; | ||
2333 | __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ | ||
2334 | __le64 LastAccessTime; | ||
2335 | __le64 LastModificationTime; | ||
2336 | __le64 Uid; | ||
2337 | __le64 Gid; | ||
2338 | __le32 Type; | ||
2339 | __le64 DevMajor; | ||
2340 | __le64 DevMinor; | ||
2341 | __le64 UniqueId; | ||
2342 | __le64 Permissions; | ||
2343 | __le64 Nlinks; | ||
2344 | char FileName[1]; | 2332 | char FileName[1]; |
2345 | } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ | 2333 | } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ |
2346 | 2334 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index c419416a42ee..b2bd83fd2aa4 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -98,9 +98,14 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, | |||
98 | extern int cifs_posix_open(char *full_path, struct inode **pinode, | 98 | extern int cifs_posix_open(char *full_path, struct inode **pinode, |
99 | struct super_block *sb, int mode, int oflags, | 99 | struct super_block *sb, int mode, int oflags, |
100 | int *poplock, __u16 *pnetfid, int xid); | 100 | int *poplock, __u16 *pnetfid, int xid); |
101 | extern void posix_fill_in_inode(struct inode *tmp_inode, | 101 | extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, |
102 | FILE_UNIX_BASIC_INFO *pData, int isNewInode); | 102 | FILE_UNIX_BASIC_INFO *info, |
103 | struct cifs_sb_info *cifs_sb); | ||
104 | extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); | ||
103 | extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); | 105 | extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); |
106 | extern struct inode *cifs_iget(struct super_block *sb, | ||
107 | struct cifs_fattr *fattr); | ||
108 | |||
104 | extern int cifs_get_inode_info(struct inode **pinode, | 109 | extern int cifs_get_inode_info(struct inode **pinode, |
105 | const unsigned char *search_path, | 110 | const unsigned char *search_path, |
106 | FILE_ALL_INFO *pfile_info, | 111 | FILE_ALL_INFO *pfile_info, |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7dc6b74f9def..a40054faed7f 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -188,6 +188,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
188 | FILE_UNIX_BASIC_INFO *presp_data; | 188 | FILE_UNIX_BASIC_INFO *presp_data; |
189 | __u32 posix_flags = 0; | 189 | __u32 posix_flags = 0; |
190 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 190 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
191 | struct cifs_fattr fattr; | ||
191 | 192 | ||
192 | cFYI(1, ("posix open %s", full_path)); | 193 | cFYI(1, ("posix open %s", full_path)); |
193 | 194 | ||
@@ -236,22 +237,21 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
236 | if (presp_data->Type == cpu_to_le32(-1)) | 237 | if (presp_data->Type == cpu_to_le32(-1)) |
237 | goto posix_open_ret; /* open ok, caller does qpathinfo */ | 238 | goto posix_open_ret; /* open ok, caller does qpathinfo */ |
238 | 239 | ||
239 | /* get new inode and set it up */ | ||
240 | if (!pinode) | 240 | if (!pinode) |
241 | goto posix_open_ret; /* caller does not need info */ | 241 | goto posix_open_ret; /* caller does not need info */ |
242 | 242 | ||
243 | cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); | ||
244 | |||
245 | /* get new inode and set it up */ | ||
243 | if (*pinode == NULL) { | 246 | if (*pinode == NULL) { |
244 | __u64 unique_id = le64_to_cpu(presp_data->UniqueId); | 247 | *pinode = cifs_iget(sb, &fattr); |
245 | *pinode = cifs_new_inode(sb, &unique_id); | 248 | if (!*pinode) { |
249 | rc = -ENOMEM; | ||
250 | goto posix_open_ret; | ||
251 | } | ||
252 | } else { | ||
253 | cifs_fattr_to_inode(*pinode, &fattr); | ||
246 | } | 254 | } |
247 | /* else an inode was passed in. Update its info, don't create one */ | ||
248 | |||
249 | /* We do not need to close the file if new_inode fails since | ||
250 | the caller will retry qpathinfo as long as inode is null */ | ||
251 | if (*pinode == NULL) | ||
252 | goto posix_open_ret; | ||
253 | |||
254 | posix_fill_in_inode(*pinode, presp_data, 1); | ||
255 | 255 | ||
256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); | 256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); |
257 | 257 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 155c9e785d0c..b22379610d71 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -77,127 +77,146 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | |||
77 | } | 77 | } |
78 | } | 78 | } |
79 | 79 | ||
80 | static void cifs_unix_info_to_inode(struct inode *inode, | 80 | /* populate an inode with info from a cifs_fattr struct */ |
81 | FILE_UNIX_BASIC_INFO *info, int force_uid_gid) | 81 | void |
82 | cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | ||
82 | { | 83 | { |
83 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 84 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
84 | struct cifsInodeInfo *cifsInfo = CIFS_I(inode); | 85 | unsigned long now = jiffies; |
85 | __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); | 86 | |
86 | __u64 end_of_file = le64_to_cpu(info->EndOfFile); | 87 | inode->i_atime = fattr->cf_atime; |
88 | inode->i_mtime = fattr->cf_mtime; | ||
89 | inode->i_ctime = fattr->cf_ctime; | ||
90 | inode->i_mode = fattr->cf_mode; | ||
91 | inode->i_rdev = fattr->cf_rdev; | ||
92 | inode->i_nlink = fattr->cf_nlink; | ||
93 | inode->i_uid = fattr->cf_uid; | ||
94 | inode->i_gid = fattr->cf_gid; | ||
95 | |||
96 | cifs_i->cifsAttrs = fattr->cf_cifsattrs; | ||
97 | cifs_i->uniqueid = fattr->cf_uniqueid; | ||
98 | |||
99 | cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, | ||
100 | cifs_i->time, now)); | ||
101 | cifs_i->time = now; | ||
102 | |||
103 | /* | ||
104 | * Can't safely change the file size here if the client is writing to | ||
105 | * it due to potential races. | ||
106 | */ | ||
107 | spin_lock(&inode->i_lock); | ||
108 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { | ||
109 | i_size_write(inode, fattr->cf_eof); | ||
110 | |||
111 | /* | ||
112 | * i_blocks is not related to (i_size / i_blksize), | ||
113 | * but instead 512 byte (2**9) size is required for | ||
114 | * calculating num blocks. | ||
115 | */ | ||
116 | inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9; | ||
117 | } | ||
118 | spin_unlock(&inode->i_lock); | ||
119 | |||
120 | cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); | ||
121 | } | ||
122 | |||
123 | /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ | ||
124 | void | ||
125 | cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, | ||
126 | struct cifs_sb_info *cifs_sb) | ||
127 | { | ||
128 | memset(fattr, 0, sizeof(*fattr)); | ||
129 | fattr->cf_uniqueid = le64_to_cpu(info->UniqueId); | ||
130 | fattr->cf_bytes = le64_to_cpu(info->NumOfBytes); | ||
131 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); | ||
87 | 132 | ||
88 | inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime); | 133 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); |
89 | inode->i_mtime = | 134 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime); |
90 | cifs_NTtimeToUnix(info->LastModificationTime); | 135 | fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange); |
91 | inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange); | 136 | fattr->cf_mode = le64_to_cpu(info->Permissions); |
92 | inode->i_mode = le64_to_cpu(info->Permissions); | ||
93 | 137 | ||
94 | /* | 138 | /* |
95 | * Since we set the inode type below we need to mask off | 139 | * Since we set the inode type below we need to mask off |
96 | * to avoid strange results if bits set above. | 140 | * to avoid strange results if bits set above. |
97 | */ | 141 | */ |
98 | inode->i_mode &= ~S_IFMT; | 142 | fattr->cf_mode &= ~S_IFMT; |
99 | switch (le32_to_cpu(info->Type)) { | 143 | switch (le32_to_cpu(info->Type)) { |
100 | case UNIX_FILE: | 144 | case UNIX_FILE: |
101 | inode->i_mode |= S_IFREG; | 145 | fattr->cf_mode |= S_IFREG; |
146 | fattr->cf_dtype = DT_REG; | ||
102 | break; | 147 | break; |
103 | case UNIX_SYMLINK: | 148 | case UNIX_SYMLINK: |
104 | inode->i_mode |= S_IFLNK; | 149 | fattr->cf_mode |= S_IFLNK; |
150 | fattr->cf_dtype = DT_LNK; | ||
105 | break; | 151 | break; |
106 | case UNIX_DIR: | 152 | case UNIX_DIR: |
107 | inode->i_mode |= S_IFDIR; | 153 | fattr->cf_mode |= S_IFDIR; |
154 | fattr->cf_dtype = DT_DIR; | ||
108 | break; | 155 | break; |
109 | case UNIX_CHARDEV: | 156 | case UNIX_CHARDEV: |
110 | inode->i_mode |= S_IFCHR; | 157 | fattr->cf_mode |= S_IFCHR; |
111 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | 158 | fattr->cf_dtype = DT_CHR; |
112 | le64_to_cpu(info->DevMinor) & MINORMASK); | 159 | fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), |
160 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
113 | break; | 161 | break; |
114 | case UNIX_BLOCKDEV: | 162 | case UNIX_BLOCKDEV: |
115 | inode->i_mode |= S_IFBLK; | 163 | fattr->cf_mode |= S_IFBLK; |
116 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | 164 | fattr->cf_dtype = DT_BLK; |
117 | le64_to_cpu(info->DevMinor) & MINORMASK); | 165 | fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), |
166 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
118 | break; | 167 | break; |
119 | case UNIX_FIFO: | 168 | case UNIX_FIFO: |
120 | inode->i_mode |= S_IFIFO; | 169 | fattr->cf_mode |= S_IFIFO; |
170 | fattr->cf_dtype = DT_FIFO; | ||
121 | break; | 171 | break; |
122 | case UNIX_SOCKET: | 172 | case UNIX_SOCKET: |
123 | inode->i_mode |= S_IFSOCK; | 173 | fattr->cf_mode |= S_IFSOCK; |
174 | fattr->cf_dtype = DT_SOCK; | ||
124 | break; | 175 | break; |
125 | default: | 176 | default: |
126 | /* safest to call it a file if we do not know */ | 177 | /* safest to call it a file if we do not know */ |
127 | inode->i_mode |= S_IFREG; | 178 | fattr->cf_mode |= S_IFREG; |
179 | fattr->cf_dtype = DT_REG; | ||
128 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); | 180 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); |
129 | break; | 181 | break; |
130 | } | 182 | } |
131 | 183 | ||
132 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) && | 184 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
133 | !force_uid_gid) | 185 | fattr->cf_uid = cifs_sb->mnt_uid; |
134 | inode->i_uid = cifs_sb->mnt_uid; | ||
135 | else | 186 | else |
136 | inode->i_uid = le64_to_cpu(info->Uid); | 187 | fattr->cf_uid = le64_to_cpu(info->Uid); |
137 | 188 | ||
138 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) && | 189 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) |
139 | !force_uid_gid) | 190 | fattr->cf_gid = cifs_sb->mnt_gid; |
140 | inode->i_gid = cifs_sb->mnt_gid; | ||
141 | else | 191 | else |
142 | inode->i_gid = le64_to_cpu(info->Gid); | 192 | fattr->cf_gid = le64_to_cpu(info->Gid); |
143 | 193 | ||
144 | inode->i_nlink = le64_to_cpu(info->Nlinks); | 194 | fattr->cf_nlink = le64_to_cpu(info->Nlinks); |
145 | |||
146 | cifsInfo->server_eof = end_of_file; | ||
147 | spin_lock(&inode->i_lock); | ||
148 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
149 | /* | ||
150 | * We can not safely change the file size here if the client | ||
151 | * is writing to it due to potential races. | ||
152 | */ | ||
153 | i_size_write(inode, end_of_file); | ||
154 | |||
155 | /* | ||
156 | * i_blocks is not related to (i_size / i_blksize), | ||
157 | * but instead 512 byte (2**9) size is required for | ||
158 | * calculating num blocks. | ||
159 | */ | ||
160 | inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
161 | } | ||
162 | spin_unlock(&inode->i_lock); | ||
163 | } | 195 | } |
164 | 196 | ||
165 | |||
166 | /* | 197 | /* |
167 | * Needed to setup inode data for the directory which is the | 198 | * Fill a cifs_fattr struct with fake inode info. |
168 | * junction to the new submount (ie to setup the fake directory | 199 | * |
169 | * which represents a DFS referral) | 200 | * Needed to setup cifs_fattr data for the directory which is the |
201 | * junction to the new submount (ie to setup the fake directory | ||
202 | * which represents a DFS referral). | ||
170 | */ | 203 | */ |
171 | static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, | 204 | void |
172 | struct super_block *sb) | 205 | cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) |
173 | { | 206 | { |
174 | struct inode *pinode = NULL; | 207 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
175 | |||
176 | memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO)); | ||
177 | 208 | ||
178 | /* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | 209 | cFYI(1, ("creating fake fattr for DFS referral")); |
179 | __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); | 210 | |
180 | __u64 UniqueId = 0; */ | 211 | memset(fattr, 0, sizeof(*fattr)); |
181 | pfnd_dat->LastStatusChange = | 212 | fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; |
182 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 213 | fattr->cf_uid = cifs_sb->mnt_uid; |
183 | pfnd_dat->LastAccessTime = | 214 | fattr->cf_gid = cifs_sb->mnt_gid; |
184 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 215 | fattr->cf_atime = CURRENT_TIME; |
185 | pfnd_dat->LastModificationTime = | 216 | fattr->cf_ctime = CURRENT_TIME; |
186 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 217 | fattr->cf_mtime = CURRENT_TIME; |
187 | pfnd_dat->Type = cpu_to_le32(UNIX_DIR); | 218 | fattr->cf_nlink = 2; |
188 | pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); | 219 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; |
189 | pfnd_dat->Nlinks = cpu_to_le64(2); | ||
190 | if (sb->s_root) | ||
191 | pinode = sb->s_root->d_inode; | ||
192 | if (pinode == NULL) | ||
193 | return; | ||
194 | |||
195 | /* fill in default values for the remaining based on root | ||
196 | inode since we can not query the server for this inode info */ | ||
197 | pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); | ||
198 | pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); | ||
199 | pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); | ||
200 | pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); | ||
201 | } | 220 | } |
202 | 221 | ||
203 | /** | 222 | /** |
@@ -244,66 +263,42 @@ cifs_new_inode(struct super_block *sb, __u64 *inum) | |||
244 | } | 263 | } |
245 | 264 | ||
246 | int cifs_get_inode_info_unix(struct inode **pinode, | 265 | int cifs_get_inode_info_unix(struct inode **pinode, |
247 | const unsigned char *full_path, struct super_block *sb, int xid) | 266 | const unsigned char *full_path, |
267 | struct super_block *sb, int xid) | ||
248 | { | 268 | { |
249 | int rc = 0; | 269 | int rc; |
250 | FILE_UNIX_BASIC_INFO find_data; | 270 | FILE_UNIX_BASIC_INFO find_data; |
251 | struct cifsTconInfo *pTcon; | 271 | struct cifs_fattr fattr; |
252 | struct inode *inode; | 272 | struct cifsTconInfo *tcon; |
253 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 273 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
254 | bool is_dfs_referral = false; | ||
255 | struct cifsInodeInfo *cifsInfo; | ||
256 | __u64 num_of_bytes; | ||
257 | __u64 end_of_file; | ||
258 | 274 | ||
259 | pTcon = cifs_sb->tcon; | 275 | tcon = cifs_sb->tcon; |
260 | cFYI(1, ("Getting info on %s", full_path)); | 276 | cFYI(1, ("Getting info on %s", full_path)); |
261 | 277 | ||
262 | /* could have done a find first instead but this returns more info */ | 278 | /* could have done a find first instead but this returns more info */ |
263 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, | 279 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, |
264 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 280 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
265 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 281 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
266 | if (rc == -EREMOTE && !is_dfs_referral) { | ||
267 | is_dfs_referral = true; | ||
268 | cFYI(DBG2, ("DFS ref")); | ||
269 | /* for DFS, server does not give us real inode data */ | ||
270 | fill_fake_finddataunix(&find_data, sb); | ||
271 | rc = 0; | ||
272 | } else if (rc) | ||
273 | goto cgiiu_exit; | ||
274 | 282 | ||
275 | num_of_bytes = le64_to_cpu(find_data.NumOfBytes); | 283 | if (!rc) { |
276 | end_of_file = le64_to_cpu(find_data.EndOfFile); | 284 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); |
285 | } else if (rc == -EREMOTE) { | ||
286 | cifs_create_dfs_fattr(&fattr, sb); | ||
287 | rc = 0; | ||
288 | } else { | ||
289 | return rc; | ||
290 | } | ||
277 | 291 | ||
278 | /* get new inode */ | ||
279 | if (*pinode == NULL) { | 292 | if (*pinode == NULL) { |
280 | __u64 unique_id = le64_to_cpu(find_data.UniqueId); | 293 | /* get new inode */ |
281 | *pinode = cifs_new_inode(sb, &unique_id); | 294 | *pinode = cifs_iget(sb, &fattr); |
282 | if (*pinode == NULL) { | 295 | if (!*pinode) |
283 | rc = -ENOMEM; | 296 | rc = -ENOMEM; |
284 | goto cgiiu_exit; | 297 | } else { |
285 | } | 298 | /* we already have inode, update it */ |
299 | cifs_fattr_to_inode(*pinode, &fattr); | ||
286 | } | 300 | } |
287 | 301 | ||
288 | inode = *pinode; | ||
289 | cifsInfo = CIFS_I(inode); | ||
290 | |||
291 | cFYI(1, ("Old time %ld", cifsInfo->time)); | ||
292 | cifsInfo->time = jiffies; | ||
293 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
294 | /* this is ok to set on every inode revalidate */ | ||
295 | atomic_set(&cifsInfo->inUse, 1); | ||
296 | |||
297 | cifs_unix_info_to_inode(inode, &find_data, 0); | ||
298 | |||
299 | if (num_of_bytes < end_of_file) | ||
300 | cFYI(1, ("allocation size less than end of file")); | ||
301 | cFYI(1, ("Size %ld and blocks %llu", | ||
302 | (unsigned long) inode->i_size, | ||
303 | (unsigned long long)inode->i_blocks)); | ||
304 | |||
305 | cifs_set_ops(inode, is_dfs_referral); | ||
306 | cgiiu_exit: | ||
307 | return rc; | 302 | return rc; |
308 | } | 303 | } |
309 | 304 | ||
@@ -695,33 +690,85 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
695 | return full_path; | 690 | return full_path; |
696 | } | 691 | } |
697 | 692 | ||
693 | static int | ||
694 | cifs_find_inode(struct inode *inode, void *opaque) | ||
695 | { | ||
696 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
697 | |||
698 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | ||
699 | return 0; | ||
700 | |||
701 | return 1; | ||
702 | } | ||
703 | |||
704 | static int | ||
705 | cifs_init_inode(struct inode *inode, void *opaque) | ||
706 | { | ||
707 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
708 | |||
709 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | /* Given fattrs, get a corresponding inode */ | ||
714 | struct inode * | ||
715 | cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) | ||
716 | { | ||
717 | unsigned long hash; | ||
718 | struct inode *inode; | ||
719 | |||
720 | cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); | ||
721 | |||
722 | /* hash down to 32-bits on 32-bit arch */ | ||
723 | hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); | ||
724 | |||
725 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); | ||
726 | |||
727 | /* we have fattrs in hand, update the inode */ | ||
728 | if (inode) { | ||
729 | cifs_fattr_to_inode(inode, fattr); | ||
730 | if (sb->s_flags & MS_NOATIME) | ||
731 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
732 | if (inode->i_state & I_NEW) { | ||
733 | inode->i_ino = hash; | ||
734 | unlock_new_inode(inode); | ||
735 | } | ||
736 | } | ||
737 | |||
738 | return inode; | ||
739 | } | ||
740 | |||
698 | /* gets root inode */ | 741 | /* gets root inode */ |
699 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 742 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) |
700 | { | 743 | { |
701 | int xid; | 744 | int xid; |
702 | struct cifs_sb_info *cifs_sb; | 745 | struct cifs_sb_info *cifs_sb; |
703 | struct inode *inode; | 746 | struct inode *inode = NULL; |
704 | long rc; | 747 | long rc; |
705 | char *full_path; | 748 | char *full_path; |
706 | 749 | ||
707 | inode = iget_locked(sb, ino); | 750 | cifs_sb = CIFS_SB(sb); |
708 | if (!inode) | ||
709 | return ERR_PTR(-ENOMEM); | ||
710 | if (!(inode->i_state & I_NEW)) | ||
711 | return inode; | ||
712 | |||
713 | cifs_sb = CIFS_SB(inode->i_sb); | ||
714 | full_path = cifs_build_path_to_root(cifs_sb); | 751 | full_path = cifs_build_path_to_root(cifs_sb); |
715 | if (full_path == NULL) | 752 | if (full_path == NULL) |
716 | return ERR_PTR(-ENOMEM); | 753 | return ERR_PTR(-ENOMEM); |
717 | 754 | ||
718 | xid = GetXid(); | 755 | xid = GetXid(); |
719 | if (cifs_sb->tcon->unix_ext) | 756 | if (cifs_sb->tcon->unix_ext) { |
720 | rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, | 757 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
721 | xid); | 758 | if (!inode) |
722 | else | 759 | return ERR_PTR(-ENOMEM); |
760 | } else { | ||
761 | inode = iget_locked(sb, ino); | ||
762 | if (!inode) | ||
763 | return ERR_PTR(-ENOMEM); | ||
764 | if (!(inode->i_state & I_NEW)) | ||
765 | return inode; | ||
766 | |||
723 | rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, | 767 | rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, |
724 | xid, NULL); | 768 | xid, NULL); |
769 | unlock_new_inode(inode); | ||
770 | } | ||
771 | |||
725 | if (rc && cifs_sb->tcon->ipc) { | 772 | if (rc && cifs_sb->tcon->ipc) { |
726 | cFYI(1, ("ipc connection - fake read inode")); | 773 | cFYI(1, ("ipc connection - fake read inode")); |
727 | inode->i_mode |= S_IFDIR; | 774 | inode->i_mode |= S_IFDIR; |
@@ -737,7 +784,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
737 | return ERR_PTR(rc); | 784 | return ERR_PTR(rc); |
738 | } | 785 | } |
739 | 786 | ||
740 | unlock_new_inode(inode); | ||
741 | 787 | ||
742 | kfree(full_path); | 788 | kfree(full_path); |
743 | /* can not call macro FreeXid here since in a void func | 789 | /* can not call macro FreeXid here since in a void func |
@@ -1063,44 +1109,6 @@ out_reval: | |||
1063 | return rc; | 1109 | return rc; |
1064 | } | 1110 | } |
1065 | 1111 | ||
1066 | void posix_fill_in_inode(struct inode *tmp_inode, | ||
1067 | FILE_UNIX_BASIC_INFO *pData, int isNewInode) | ||
1068 | { | ||
1069 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
1070 | loff_t local_size; | ||
1071 | struct timespec local_mtime; | ||
1072 | |||
1073 | cifsInfo->time = jiffies; | ||
1074 | atomic_inc(&cifsInfo->inUse); | ||
1075 | |||
1076 | /* save mtime and size */ | ||
1077 | local_mtime = tmp_inode->i_mtime; | ||
1078 | local_size = tmp_inode->i_size; | ||
1079 | |||
1080 | cifs_unix_info_to_inode(tmp_inode, pData, 1); | ||
1081 | cifs_set_ops(tmp_inode, false); | ||
1082 | |||
1083 | if (!S_ISREG(tmp_inode->i_mode)) | ||
1084 | return; | ||
1085 | |||
1086 | /* | ||
1087 | * No sense invalidating pages for new inode | ||
1088 | * since we we have not started caching | ||
1089 | * readahead file data yet. | ||
1090 | */ | ||
1091 | if (isNewInode) | ||
1092 | return; | ||
1093 | |||
1094 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
1095 | (local_size == tmp_inode->i_size)) { | ||
1096 | cFYI(1, ("inode exists but unchanged")); | ||
1097 | } else { | ||
1098 | /* file may have changed on server */ | ||
1099 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
1100 | invalidate_remote_inode(tmp_inode); | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1104 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | 1112 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) |
1105 | { | 1113 | { |
1106 | int rc = 0, tmprc; | 1114 | int rc = 0, tmprc; |
@@ -1109,6 +1117,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1109 | struct cifsTconInfo *pTcon; | 1117 | struct cifsTconInfo *pTcon; |
1110 | char *full_path = NULL; | 1118 | char *full_path = NULL; |
1111 | struct inode *newinode = NULL; | 1119 | struct inode *newinode = NULL; |
1120 | struct cifs_fattr fattr; | ||
1112 | 1121 | ||
1113 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); | 1122 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); |
1114 | 1123 | ||
@@ -1148,7 +1157,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1148 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 1157 | cFYI(1, ("posix mkdir returned 0x%x", rc)); |
1149 | d_drop(direntry); | 1158 | d_drop(direntry); |
1150 | } else { | 1159 | } else { |
1151 | __u64 unique_id; | ||
1152 | if (pInfo->Type == cpu_to_le32(-1)) { | 1160 | if (pInfo->Type == cpu_to_le32(-1)) { |
1153 | /* no return info, go query for it */ | 1161 | /* no return info, go query for it */ |
1154 | kfree(pInfo); | 1162 | kfree(pInfo); |
@@ -1162,20 +1170,15 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1162 | else | 1170 | else |
1163 | direntry->d_op = &cifs_dentry_ops; | 1171 | direntry->d_op = &cifs_dentry_ops; |
1164 | 1172 | ||
1165 | unique_id = le64_to_cpu(pInfo->UniqueId); | 1173 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); |
1166 | newinode = cifs_new_inode(inode->i_sb, &unique_id); | 1174 | newinode = cifs_iget(inode->i_sb, &fattr); |
1167 | if (newinode == NULL) { | 1175 | if (!newinode) { |
1168 | kfree(pInfo); | 1176 | kfree(pInfo); |
1169 | goto mkdir_get_info; | 1177 | goto mkdir_get_info; |
1170 | } | 1178 | } |
1171 | 1179 | ||
1172 | newinode->i_nlink = 2; | ||
1173 | d_instantiate(direntry, newinode); | 1180 | d_instantiate(direntry, newinode); |
1174 | 1181 | ||
1175 | /* we already checked in POSIXCreate whether | ||
1176 | frame was long enough */ | ||
1177 | posix_fill_in_inode(direntry->d_inode, | ||
1178 | pInfo, 1 /* NewInode */); | ||
1179 | #ifdef CONFIG_CIFS_DEBUG2 | 1182 | #ifdef CONFIG_CIFS_DEBUG2 |
1180 | cFYI(1, ("instantiated dentry %p %s to inode %p", | 1183 | cFYI(1, ("instantiated dentry %p %s to inode %p", |
1181 | direntry, direntry->d_name.name, newinode)); | 1184 | direntry, direntry->d_name.name, newinode)); |
@@ -1622,6 +1625,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1622 | if (!err) { | 1625 | if (!err) { |
1623 | generic_fillattr(dentry->d_inode, stat); | 1626 | generic_fillattr(dentry->d_inode, stat); |
1624 | stat->blksize = CIFS_MAX_MSGSIZE; | 1627 | stat->blksize = CIFS_MAX_MSGSIZE; |
1628 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | ||
1625 | } | 1629 | } |
1626 | return err; | 1630 | return err; |
1627 | } | 1631 | } |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 86d0055dc529..231aa6953f83 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -63,6 +63,55 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) | |||
63 | } | 63 | } |
64 | #endif /* DEBUG2 */ | 64 | #endif /* DEBUG2 */ |
65 | 65 | ||
66 | /* | ||
67 | * Find the dentry that matches "name". If there isn't one, create one. If it's | ||
68 | * a negative dentry or the uniqueid changed, then drop it and recreate it. | ||
69 | */ | ||
70 | static struct dentry * | ||
71 | cifs_readdir_lookup(struct dentry *parent, struct qstr *name, | ||
72 | struct cifs_fattr *fattr) | ||
73 | { | ||
74 | struct dentry *dentry, *alias; | ||
75 | struct inode *inode; | ||
76 | struct super_block *sb = parent->d_inode->i_sb; | ||
77 | |||
78 | cFYI(1, ("For %s", name->name)); | ||
79 | |||
80 | dentry = d_lookup(parent, name); | ||
81 | if (dentry) { | ||
82 | /* FIXME: check for inode number changes? */ | ||
83 | if (dentry->d_inode != NULL) | ||
84 | return dentry; | ||
85 | d_drop(dentry); | ||
86 | dput(dentry); | ||
87 | } | ||
88 | |||
89 | dentry = d_alloc(parent, name); | ||
90 | if (dentry == NULL) | ||
91 | return NULL; | ||
92 | |||
93 | inode = cifs_iget(sb, fattr); | ||
94 | if (!inode) { | ||
95 | dput(dentry); | ||
96 | return NULL; | ||
97 | } | ||
98 | |||
99 | if (CIFS_SB(sb)->tcon->nocase) | ||
100 | dentry->d_op = &cifs_ci_dentry_ops; | ||
101 | else | ||
102 | dentry->d_op = &cifs_dentry_ops; | ||
103 | |||
104 | alias = d_materialise_unique(dentry, inode); | ||
105 | if (alias != NULL) { | ||
106 | dput(dentry); | ||
107 | if (IS_ERR(alias)) | ||
108 | return NULL; | ||
109 | dentry = alias; | ||
110 | } | ||
111 | |||
112 | return dentry; | ||
113 | } | ||
114 | |||
66 | /* Returns 1 if new inode created, 2 if both dentry and inode were */ | 115 | /* Returns 1 if new inode created, 2 if both dentry and inode were */ |
67 | /* Might check in the future if inode number changed so we can rehash inode */ | 116 | /* Might check in the future if inode number changed so we can rehash inode */ |
68 | static int | 117 | static int |
@@ -76,7 +125,6 @@ construct_dentry(struct qstr *qstring, struct file *file, | |||
76 | 125 | ||
77 | cFYI(1, ("For %s", qstring->name)); | 126 | cFYI(1, ("For %s", qstring->name)); |
78 | 127 | ||
79 | qstring->hash = full_name_hash(qstring->name, qstring->len); | ||
80 | tmp_dentry = d_lookup(file->f_path.dentry, qstring); | 128 | tmp_dentry = d_lookup(file->f_path.dentry, qstring); |
81 | if (tmp_dentry) { | 129 | if (tmp_dentry) { |
82 | /* BB: overwrite old name? i.e. tmp_dentry->d_name and | 130 | /* BB: overwrite old name? i.e. tmp_dentry->d_name and |
@@ -299,140 +347,6 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
299 | } | 347 | } |
300 | } | 348 | } |
301 | 349 | ||
302 | static void unix_fill_in_inode(struct inode *tmp_inode, | ||
303 | FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode) | ||
304 | { | ||
305 | loff_t local_size; | ||
306 | struct timespec local_mtime; | ||
307 | |||
308 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
309 | struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); | ||
310 | |||
311 | __u32 type = le32_to_cpu(pfindData->Type); | ||
312 | __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes); | ||
313 | __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile); | ||
314 | cifsInfo->time = jiffies; | ||
315 | atomic_inc(&cifsInfo->inUse); | ||
316 | |||
317 | /* save mtime and size */ | ||
318 | local_mtime = tmp_inode->i_mtime; | ||
319 | local_size = tmp_inode->i_size; | ||
320 | |||
321 | tmp_inode->i_atime = | ||
322 | cifs_NTtimeToUnix(pfindData->LastAccessTime); | ||
323 | tmp_inode->i_mtime = | ||
324 | cifs_NTtimeToUnix(pfindData->LastModificationTime); | ||
325 | tmp_inode->i_ctime = | ||
326 | cifs_NTtimeToUnix(pfindData->LastStatusChange); | ||
327 | |||
328 | tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); | ||
329 | /* since we set the inode type below we need to mask off type | ||
330 | to avoid strange results if bits above were corrupt */ | ||
331 | tmp_inode->i_mode &= ~S_IFMT; | ||
332 | if (type == UNIX_FILE) { | ||
333 | *pobject_type = DT_REG; | ||
334 | tmp_inode->i_mode |= S_IFREG; | ||
335 | } else if (type == UNIX_SYMLINK) { | ||
336 | *pobject_type = DT_LNK; | ||
337 | tmp_inode->i_mode |= S_IFLNK; | ||
338 | } else if (type == UNIX_DIR) { | ||
339 | *pobject_type = DT_DIR; | ||
340 | tmp_inode->i_mode |= S_IFDIR; | ||
341 | } else if (type == UNIX_CHARDEV) { | ||
342 | *pobject_type = DT_CHR; | ||
343 | tmp_inode->i_mode |= S_IFCHR; | ||
344 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), | ||
345 | le64_to_cpu(pfindData->DevMinor) & MINORMASK); | ||
346 | } else if (type == UNIX_BLOCKDEV) { | ||
347 | *pobject_type = DT_BLK; | ||
348 | tmp_inode->i_mode |= S_IFBLK; | ||
349 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), | ||
350 | le64_to_cpu(pfindData->DevMinor) & MINORMASK); | ||
351 | } else if (type == UNIX_FIFO) { | ||
352 | *pobject_type = DT_FIFO; | ||
353 | tmp_inode->i_mode |= S_IFIFO; | ||
354 | } else if (type == UNIX_SOCKET) { | ||
355 | *pobject_type = DT_SOCK; | ||
356 | tmp_inode->i_mode |= S_IFSOCK; | ||
357 | } else { | ||
358 | /* safest to just call it a file */ | ||
359 | *pobject_type = DT_REG; | ||
360 | tmp_inode->i_mode |= S_IFREG; | ||
361 | cFYI(1, ("unknown inode type %d", type)); | ||
362 | } | ||
363 | |||
364 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) | ||
365 | tmp_inode->i_uid = cifs_sb->mnt_uid; | ||
366 | else | ||
367 | tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); | ||
368 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) | ||
369 | tmp_inode->i_gid = cifs_sb->mnt_gid; | ||
370 | else | ||
371 | tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); | ||
372 | tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); | ||
373 | |||
374 | cifsInfo->server_eof = end_of_file; | ||
375 | spin_lock(&tmp_inode->i_lock); | ||
376 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
377 | /* can not safely change the file size here if the | ||
378 | client is writing to it due to potential races */ | ||
379 | i_size_write(tmp_inode, end_of_file); | ||
380 | |||
381 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | ||
382 | /* for this calculation, not the real blocksize */ | ||
383 | tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
384 | } | ||
385 | spin_unlock(&tmp_inode->i_lock); | ||
386 | |||
387 | if (S_ISREG(tmp_inode->i_mode)) { | ||
388 | cFYI(1, ("File inode")); | ||
389 | tmp_inode->i_op = &cifs_file_inode_ops; | ||
390 | |||
391 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||
392 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
393 | tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; | ||
394 | else | ||
395 | tmp_inode->i_fop = &cifs_file_direct_ops; | ||
396 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
397 | tmp_inode->i_fop = &cifs_file_nobrl_ops; | ||
398 | else | ||
399 | tmp_inode->i_fop = &cifs_file_ops; | ||
400 | |||
401 | if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | ||
402 | (cifs_sb->tcon->ses->server->maxBuf < | ||
403 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) | ||
404 | tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
405 | else | ||
406 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | ||
407 | |||
408 | if (isNewInode) | ||
409 | return; /* No sense invalidating pages for new inode | ||
410 | since we have not started caching readahead | ||
411 | file data for it yet */ | ||
412 | |||
413 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
414 | (local_size == tmp_inode->i_size)) { | ||
415 | cFYI(1, ("inode exists but unchanged")); | ||
416 | } else { | ||
417 | /* file may have changed on server */ | ||
418 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
419 | invalidate_remote_inode(tmp_inode); | ||
420 | } | ||
421 | } else if (S_ISDIR(tmp_inode->i_mode)) { | ||
422 | cFYI(1, ("Directory inode")); | ||
423 | tmp_inode->i_op = &cifs_dir_inode_ops; | ||
424 | tmp_inode->i_fop = &cifs_dir_ops; | ||
425 | } else if (S_ISLNK(tmp_inode->i_mode)) { | ||
426 | cFYI(1, ("Symbolic Link inode")); | ||
427 | tmp_inode->i_op = &cifs_symlink_inode_ops; | ||
428 | /* tmp_inode->i_fop = *//* do not need to set to anything */ | ||
429 | } else { | ||
430 | cFYI(1, ("Special inode")); | ||
431 | init_special_inode(tmp_inode, tmp_inode->i_mode, | ||
432 | tmp_inode->i_rdev); | ||
433 | } | ||
434 | } | ||
435 | |||
436 | /* BB eventually need to add the following helper function to | 350 | /* BB eventually need to add the following helper function to |
437 | resolve NT_STATUS_STOPPED_ON_SYMLINK return code when | 351 | resolve NT_STATUS_STOPPED_ON_SYMLINK return code when |
438 | we try to do FindFirst on (NTFS) directory symlinks */ | 352 | we try to do FindFirst on (NTFS) directory symlinks */ |
@@ -872,7 +786,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
872 | len = strnlen(filename, PATH_MAX); | 786 | len = strnlen(filename, PATH_MAX); |
873 | } | 787 | } |
874 | 788 | ||
875 | *pinum = le64_to_cpu(pFindData->UniqueId); | 789 | *pinum = le64_to_cpu(pFindData->basic.UniqueId); |
876 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { | 790 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { |
877 | FILE_DIRECTORY_INFO *pFindData = | 791 | FILE_DIRECTORY_INFO *pFindData = |
878 | (FILE_DIRECTORY_INFO *)current_entry; | 792 | (FILE_DIRECTORY_INFO *)current_entry; |
@@ -934,9 +848,11 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
934 | struct cifsFileInfo *pCifsF; | 848 | struct cifsFileInfo *pCifsF; |
935 | unsigned int obj_type; | 849 | unsigned int obj_type; |
936 | __u64 inum; | 850 | __u64 inum; |
851 | ino_t ino; | ||
937 | struct cifs_sb_info *cifs_sb; | 852 | struct cifs_sb_info *cifs_sb; |
938 | struct inode *tmp_inode; | 853 | struct inode *tmp_inode; |
939 | struct dentry *tmp_dentry; | 854 | struct dentry *tmp_dentry; |
855 | struct cifs_fattr fattr; | ||
940 | 856 | ||
941 | /* get filename and len into qstring */ | 857 | /* get filename and len into qstring */ |
942 | /* get dentry */ | 858 | /* get dentry */ |
@@ -967,39 +883,49 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
967 | return rc; | 883 | return rc; |
968 | 884 | ||
969 | /* only these two infolevels return valid inode numbers */ | 885 | /* only these two infolevels return valid inode numbers */ |
970 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX || | 886 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) { |
971 | pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) | 887 | cifs_unix_basic_to_fattr(&fattr, |
972 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, | 888 | &((FILE_UNIX_INFO *) pfindEntry)->basic, |
973 | &inum); | 889 | cifs_sb); |
974 | else | 890 | tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, |
975 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, | 891 | &fattr); |
976 | NULL); | 892 | obj_type = fattr.cf_dtype; |
893 | ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); | ||
894 | } else { | ||
895 | if (pCifsF->srch_inf.info_level == | ||
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); | ||
977 | 902 | ||
978 | if ((tmp_inode == NULL) || (tmp_dentry == NULL)) | 903 | if ((tmp_inode == NULL) || (tmp_dentry == NULL)) { |
979 | return -ENOMEM; | 904 | rc = -ENOMEM; |
905 | goto out; | ||
906 | } | ||
980 | 907 | ||
981 | /* we pass in rc below, indicating whether it is a new inode, | 908 | /* we pass in rc below, indicating whether it is a new inode, |
982 | so we can figure out whether to invalidate the inode cached | 909 | * so we can figure out whether to invalidate the inode cached |
983 | data if the file has changed */ | 910 | * data if the file has changed |
984 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) | 911 | */ |
985 | unix_fill_in_inode(tmp_inode, | 912 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) |
986 | (FILE_UNIX_INFO *)pfindEntry, | 913 | fill_in_inode(tmp_inode, 0, pfindEntry, &obj_type, rc); |
987 | &obj_type, rc); | 914 | else |
988 | else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) | 915 | fill_in_inode(tmp_inode, 1, pfindEntry, &obj_type, rc); |
989 | fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */, | ||
990 | pfindEntry, &obj_type, rc); | ||
991 | else | ||
992 | fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc); | ||
993 | 916 | ||
994 | if (rc) /* new inode - needs to be tied to dentry */ { | 917 | /* new inode - needs to be tied to dentry */ |
995 | d_instantiate(tmp_dentry, tmp_inode); | 918 | if (rc) { |
996 | if (rc == 2) | 919 | d_instantiate(tmp_dentry, tmp_inode); |
997 | d_rehash(tmp_dentry); | 920 | if (rc == 2) |
998 | } | 921 | d_rehash(tmp_dentry); |
922 | } | ||
999 | 923 | ||
924 | ino = cifs_uniqueid_to_ino_t(tmp_inode->i_ino); | ||
925 | } | ||
1000 | 926 | ||
1001 | rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, | 927 | rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, |
1002 | tmp_inode->i_ino, obj_type); | 928 | ino, obj_type); |
1003 | if (rc) { | 929 | if (rc) { |
1004 | cFYI(1, ("filldir rc = %d", rc)); | 930 | cFYI(1, ("filldir rc = %d", rc)); |
1005 | /* we can not return filldir errors to the caller | 931 | /* we can not return filldir errors to the caller |
@@ -1008,6 +934,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
1008 | rc = -EOVERFLOW; | 934 | rc = -EOVERFLOW; |
1009 | } | 935 | } |
1010 | 936 | ||
937 | out: | ||
1011 | dput(tmp_dentry); | 938 | dput(tmp_dentry); |
1012 | return rc; | 939 | return rc; |
1013 | } | 940 | } |