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/cifs/inode.c | |
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/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 380 |
1 files changed, 192 insertions, 188 deletions
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 | } |