aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c202
1 files changed, 168 insertions, 34 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 923d071163b2..05b525812adb 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -41,7 +41,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
41 char *tmp_path; 41 char *tmp_path;
42 42
43 pTcon = cifs_sb->tcon; 43 pTcon = cifs_sb->tcon;
44 cFYI(1, (" Getting info on %s ", search_path)); 44 cFYI(1, ("Getting info on %s ", search_path));
45 /* could have done a find first instead but this returns more info */ 45 /* could have done a find first instead but this returns more info */
46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, 46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -97,9 +97,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
97 inode = *pinode; 97 inode = *pinode;
98 cifsInfo = CIFS_I(inode); 98 cifsInfo = CIFS_I(inode);
99 99
100 cFYI(1, (" Old time %ld ", cifsInfo->time)); 100 cFYI(1, ("Old time %ld ", cifsInfo->time));
101 cifsInfo->time = jiffies; 101 cifsInfo->time = jiffies;
102 cFYI(1, (" New time %ld ", cifsInfo->time)); 102 cFYI(1, ("New time %ld ", cifsInfo->time));
103 /* this is ok to set on every inode revalidate */ 103 /* this is ok to set on every inode revalidate */
104 atomic_set(&cifsInfo->inUse,1); 104 atomic_set(&cifsInfo->inUse,1);
105 105
@@ -111,6 +111,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
111 inode->i_ctime = 111 inode->i_ctime =
112 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange)); 112 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
113 inode->i_mode = le64_to_cpu(findData.Permissions); 113 inode->i_mode = le64_to_cpu(findData.Permissions);
114 /* since we set the inode type below we need to mask off
115 to avoid strange results if bits set above */
116 inode->i_mode &= ~S_IFMT;
114 if (type == UNIX_FILE) { 117 if (type == UNIX_FILE) {
115 inode->i_mode |= S_IFREG; 118 inode->i_mode |= S_IFREG;
116 } else if (type == UNIX_SYMLINK) { 119 } else if (type == UNIX_SYMLINK) {
@@ -129,6 +132,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
129 inode->i_mode |= S_IFIFO; 132 inode->i_mode |= S_IFIFO;
130 } else if (type == UNIX_SOCKET) { 133 } else if (type == UNIX_SOCKET) {
131 inode->i_mode |= S_IFSOCK; 134 inode->i_mode |= S_IFSOCK;
135 } else {
136 /* safest to call it a file if we do not know */
137 inode->i_mode |= S_IFREG;
138 cFYI(1,("unknown type %d",type));
132 } 139 }
133 inode->i_uid = le64_to_cpu(findData.Uid); 140 inode->i_uid = le64_to_cpu(findData.Uid);
134 inode->i_gid = le64_to_cpu(findData.Gid); 141 inode->i_gid = le64_to_cpu(findData.Gid);
@@ -155,34 +162,39 @@ int cifs_get_inode_info_unix(struct inode **pinode,
155 } 162 }
156 163
157 if (num_of_bytes < end_of_file) 164 if (num_of_bytes < end_of_file)
158 cFYI(1, ("allocation size less than end of file ")); 165 cFYI(1, ("allocation size less than end of file"));
159 cFYI(1, 166 cFYI(1,
160 ("Size %ld and blocks %ld", 167 ("Size %ld and blocks %ld",
161 (unsigned long) inode->i_size, inode->i_blocks)); 168 (unsigned long) inode->i_size, inode->i_blocks));
162 if (S_ISREG(inode->i_mode)) { 169 if (S_ISREG(inode->i_mode)) {
163 cFYI(1, (" File inode ")); 170 cFYI(1, ("File inode"));
164 inode->i_op = &cifs_file_inode_ops; 171 inode->i_op = &cifs_file_inode_ops;
165 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 172 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
166 inode->i_fop = &cifs_file_direct_ops; 173 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
167 else 174 inode->i_fop =
175 &cifs_file_direct_nobrl_ops;
176 else
177 inode->i_fop = &cifs_file_direct_ops;
178 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
179 inode->i_fop = &cifs_file_nobrl_ops;
180 else /* not direct, send byte range locks */
168 inode->i_fop = &cifs_file_ops; 181 inode->i_fop = &cifs_file_ops;
169 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 182
170 inode->i_fop->lock = NULL;
171 inode->i_data.a_ops = &cifs_addr_ops; 183 inode->i_data.a_ops = &cifs_addr_ops;
172 /* check if server can support readpages */ 184 /* check if server can support readpages */
173 if(pTcon->ses->server->maxBuf < 185 if(pTcon->ses->server->maxBuf <
174 4096 + MAX_CIFS_HDR_SIZE) 186 4096 + MAX_CIFS_HDR_SIZE)
175 inode->i_data.a_ops->readpages = NULL; 187 inode->i_data.a_ops->readpages = NULL;
176 } else if (S_ISDIR(inode->i_mode)) { 188 } else if (S_ISDIR(inode->i_mode)) {
177 cFYI(1, (" Directory inode")); 189 cFYI(1, ("Directory inode"));
178 inode->i_op = &cifs_dir_inode_ops; 190 inode->i_op = &cifs_dir_inode_ops;
179 inode->i_fop = &cifs_dir_ops; 191 inode->i_fop = &cifs_dir_ops;
180 } else if (S_ISLNK(inode->i_mode)) { 192 } else if (S_ISLNK(inode->i_mode)) {
181 cFYI(1, (" Symbolic Link inode ")); 193 cFYI(1, ("Symbolic Link inode"));
182 inode->i_op = &cifs_symlink_inode_ops; 194 inode->i_op = &cifs_symlink_inode_ops;
183 /* tmp_inode->i_fop = */ /* do not need to set to anything */ 195 /* tmp_inode->i_fop = */ /* do not need to set to anything */
184 } else { 196 } else {
185 cFYI(1, (" Init special inode ")); 197 cFYI(1, ("Init special inode"));
186 init_special_inode(inode, inode->i_mode, 198 init_special_inode(inode, inode->i_mode,
187 inode->i_rdev); 199 inode->i_rdev);
188 } 200 }
@@ -190,6 +202,111 @@ int cifs_get_inode_info_unix(struct inode **pinode,
190 return rc; 202 return rc;
191} 203}
192 204
205static int decode_sfu_inode(struct inode * inode, __u64 size,
206 const unsigned char *path,
207 struct cifs_sb_info *cifs_sb, int xid)
208{
209 int rc;
210 int oplock = FALSE;
211 __u16 netfid;
212 struct cifsTconInfo *pTcon = cifs_sb->tcon;
213 char buf[24];
214 unsigned int bytes_read;
215 char * pbuf;
216
217 pbuf = buf;
218
219 if(size == 0) {
220 inode->i_mode |= S_IFIFO;
221 return 0;
222 } else if (size < 8) {
223 return -EINVAL; /* EOPNOTSUPP? */
224 }
225
226 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
227 CREATE_NOT_DIR, &netfid, &oplock, NULL,
228 cifs_sb->local_nls,
229 cifs_sb->mnt_cifs_flags &
230 CIFS_MOUNT_MAP_SPECIAL_CHR);
231 if (rc==0) {
232 /* Read header */
233 rc = CIFSSMBRead(xid, pTcon,
234 netfid,
235 24 /* length */, 0 /* offset */,
236 &bytes_read, &pbuf);
237 if((rc == 0) && (bytes_read >= 8)) {
238 if(memcmp("IntxBLK", pbuf, 8) == 0) {
239 cFYI(1,("Block device"));
240 inode->i_mode |= S_IFBLK;
241 if(bytes_read == 24) {
242 /* we have enough to decode dev num */
243 __u64 mjr; /* major */
244 __u64 mnr; /* minor */
245 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
246 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
247 inode->i_rdev = MKDEV(mjr, mnr);
248 }
249 } else if(memcmp("IntxCHR", pbuf, 8) == 0) {
250 cFYI(1,("Char device"));
251 inode->i_mode |= S_IFCHR;
252 if(bytes_read == 24) {
253 /* we have enough to decode dev num */
254 __u64 mjr; /* major */
255 __u64 mnr; /* minor */
256 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
257 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
258 inode->i_rdev = MKDEV(mjr, mnr);
259 }
260 } else if(memcmp("IntxLNK", pbuf, 7) == 0) {
261 cFYI(1,("Symlink"));
262 inode->i_mode |= S_IFLNK;
263 } else {
264 inode->i_mode |= S_IFREG; /* file? */
265 rc = -EOPNOTSUPP;
266 }
267 } else {
268 inode->i_mode |= S_IFREG; /* then it is a file */
269 rc = -EOPNOTSUPP; /* or some unknown SFU type */
270 }
271 CIFSSMBClose(xid, pTcon, netfid);
272 }
273 return rc;
274
275}
276
277#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
278
279static int get_sfu_uid_mode(struct inode * inode,
280 const unsigned char *path,
281 struct cifs_sb_info *cifs_sb, int xid)
282{
283#ifdef CONFIG_CIFS_XATTR
284 ssize_t rc;
285 char ea_value[4];
286 __u32 mode;
287
288 rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
289 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
290 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
291 if(rc < 0)
292 return (int)rc;
293 else if (rc > 3) {
294 mode = le32_to_cpu(*((__le32 *)ea_value));
295 inode->i_mode &= ~SFBITS_MASK;
296 cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode));
297 inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
298 cFYI(1,("special mode bits 0%o", mode));
299 return 0;
300 } else {
301 return 0;
302 }
303#else
304 return -EOPNOTSUPP;
305#endif
306
307
308}
309
193int cifs_get_inode_info(struct inode **pinode, 310int cifs_get_inode_info(struct inode **pinode,
194 const unsigned char *search_path, FILE_ALL_INFO *pfindData, 311 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
195 struct super_block *sb, int xid) 312 struct super_block *sb, int xid)
@@ -202,7 +319,7 @@ int cifs_get_inode_info(struct inode **pinode,
202 char *buf = NULL; 319 char *buf = NULL;
203 320
204 pTcon = cifs_sb->tcon; 321 pTcon = cifs_sb->tcon;
205 cFYI(1,("Getting info on %s ", search_path)); 322 cFYI(1,("Getting info on %s", search_path));
206 323
207 if ((pfindData == NULL) && (*pinode != NULL)) { 324 if ((pfindData == NULL) && (*pinode != NULL)) {
208 if (CIFS_I(*pinode)->clientCanCacheRead) { 325 if (CIFS_I(*pinode)->clientCanCacheRead) {
@@ -303,9 +420,9 @@ int cifs_get_inode_info(struct inode **pinode,
303 inode = *pinode; 420 inode = *pinode;
304 cifsInfo = CIFS_I(inode); 421 cifsInfo = CIFS_I(inode);
305 cifsInfo->cifsAttrs = attr; 422 cifsInfo->cifsAttrs = attr;
306 cFYI(1, (" Old time %ld ", cifsInfo->time)); 423 cFYI(1, ("Old time %ld ", cifsInfo->time));
307 cifsInfo->time = jiffies; 424 cifsInfo->time = jiffies;
308 cFYI(1, (" New time %ld ", cifsInfo->time)); 425 cFYI(1, ("New time %ld ", cifsInfo->time));
309 426
310 /* blksize needs to be multiple of two. So safer to default to 427 /* blksize needs to be multiple of two. So safer to default to
311 blksize and blkbits set in superblock so 2**blkbits and blksize 428 blksize and blkbits set in superblock so 2**blkbits and blksize
@@ -319,13 +436,15 @@ int cifs_get_inode_info(struct inode **pinode,
319 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 436 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
320 inode->i_ctime = 437 inode->i_ctime =
321 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); 438 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
322 cFYI(0, (" Attributes came in as 0x%x ", attr)); 439 cFYI(0, ("Attributes came in as 0x%x ", attr));
323 440
324 /* set default mode. will override for dirs below */ 441 /* set default mode. will override for dirs below */
325 if (atomic_read(&cifsInfo->inUse) == 0) 442 if (atomic_read(&cifsInfo->inUse) == 0)
326 /* new inode, can safely set these fields */ 443 /* new inode, can safely set these fields */
327 inode->i_mode = cifs_sb->mnt_file_mode; 444 inode->i_mode = cifs_sb->mnt_file_mode;
328 445 else /* since we set the inode type below we need to mask off
446 to avoid strange results if type changes and both get orred in */
447 inode->i_mode &= ~S_IFMT;
329/* if (attr & ATTR_REPARSE) */ 448/* if (attr & ATTR_REPARSE) */
330 /* We no longer handle these as symlinks because we could not 449 /* We no longer handle these as symlinks because we could not
331 follow them due to the absolute path with drive letter */ 450 follow them due to the absolute path with drive letter */
@@ -340,10 +459,16 @@ int cifs_get_inode_info(struct inode **pinode,
340 (pfindData->EndOfFile == 0)) { 459 (pfindData->EndOfFile == 0)) {
341 inode->i_mode = cifs_sb->mnt_file_mode; 460 inode->i_mode = cifs_sb->mnt_file_mode;
342 inode->i_mode |= S_IFIFO; 461 inode->i_mode |= S_IFIFO;
343/* BB Finish for SFU style symlinks and devies */ 462/* BB Finish for SFU style symlinks and devices */
344/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 463 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
345 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */ 464 (cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
346 465 if (decode_sfu_inode(inode,
466 le64_to_cpu(pfindData->EndOfFile),
467 search_path,
468 cifs_sb, xid)) {
469 cFYI(1,("Unrecognized sfu inode type"));
470 }
471 cFYI(1,("sfu mode 0%o",inode->i_mode));
347 } else { 472 } else {
348 inode->i_mode |= S_IFREG; 473 inode->i_mode |= S_IFREG;
349 /* treat the dos attribute of read-only as read-only 474 /* treat the dos attribute of read-only as read-only
@@ -368,7 +493,10 @@ int cifs_get_inode_info(struct inode **pinode,
368 493
369 /* BB fill in uid and gid here? with help from winbind? 494 /* BB fill in uid and gid here? with help from winbind?
370 or retrieve from NTFS stream extended attribute */ 495 or retrieve from NTFS stream extended attribute */
371 if (atomic_read(&cifsInfo->inUse) == 0) { 496 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
497 /* fill in uid, gid, mode from server ACL */
498 get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
499 } else if (atomic_read(&cifsInfo->inUse) == 0) {
372 inode->i_uid = cifs_sb->mnt_uid; 500 inode->i_uid = cifs_sb->mnt_uid;
373 inode->i_gid = cifs_sb->mnt_gid; 501 inode->i_gid = cifs_sb->mnt_gid;
374 /* set so we do not keep refreshing these fields with 502 /* set so we do not keep refreshing these fields with
@@ -377,24 +505,29 @@ int cifs_get_inode_info(struct inode **pinode,
377 } 505 }
378 506
379 if (S_ISREG(inode->i_mode)) { 507 if (S_ISREG(inode->i_mode)) {
380 cFYI(1, (" File inode ")); 508 cFYI(1, ("File inode"));
381 inode->i_op = &cifs_file_inode_ops; 509 inode->i_op = &cifs_file_inode_ops;
382 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 510 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
383 inode->i_fop = &cifs_file_direct_ops; 511 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
384 else 512 inode->i_fop =
513 &cifs_file_direct_nobrl_ops;
514 else
515 inode->i_fop = &cifs_file_direct_ops;
516 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
517 inode->i_fop = &cifs_file_nobrl_ops;
518 else /* not direct, send byte range locks */
385 inode->i_fop = &cifs_file_ops; 519 inode->i_fop = &cifs_file_ops;
386 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 520
387 inode->i_fop->lock = NULL;
388 inode->i_data.a_ops = &cifs_addr_ops; 521 inode->i_data.a_ops = &cifs_addr_ops;
389 if(pTcon->ses->server->maxBuf < 522 if(pTcon->ses->server->maxBuf <
390 4096 + MAX_CIFS_HDR_SIZE) 523 4096 + MAX_CIFS_HDR_SIZE)
391 inode->i_data.a_ops->readpages = NULL; 524 inode->i_data.a_ops->readpages = NULL;
392 } else if (S_ISDIR(inode->i_mode)) { 525 } else if (S_ISDIR(inode->i_mode)) {
393 cFYI(1, (" Directory inode ")); 526 cFYI(1, ("Directory inode"));
394 inode->i_op = &cifs_dir_inode_ops; 527 inode->i_op = &cifs_dir_inode_ops;
395 inode->i_fop = &cifs_dir_ops; 528 inode->i_fop = &cifs_dir_ops;
396 } else if (S_ISLNK(inode->i_mode)) { 529 } else if (S_ISLNK(inode->i_mode)) {
397 cFYI(1, (" Symbolic Link inode ")); 530 cFYI(1, ("Symbolic Link inode"));
398 inode->i_op = &cifs_symlink_inode_ops; 531 inode->i_op = &cifs_symlink_inode_ops;
399 } else { 532 } else {
400 init_special_inode(inode, inode->i_mode, 533 init_special_inode(inode, inode->i_mode,
@@ -431,7 +564,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
431 struct cifsInodeInfo *cifsInode; 564 struct cifsInodeInfo *cifsInode;
432 FILE_BASIC_INFO *pinfo_buf; 565 FILE_BASIC_INFO *pinfo_buf;
433 566
434 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode)); 567 cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode));
435 568
436 xid = GetXid(); 569 xid = GetXid();
437 570
@@ -651,7 +784,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
651 char *full_path = NULL; 784 char *full_path = NULL;
652 struct cifsInodeInfo *cifsInode; 785 struct cifsInodeInfo *cifsInode;
653 786
654 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode)); 787 cFYI(1, ("cifs_rmdir, inode = 0x%p with ", inode));
655 788
656 xid = GetXid(); 789 xid = GetXid();
657 790
@@ -970,7 +1103,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
970 1103
971 xid = GetXid(); 1104 xid = GetXid();
972 1105
973 cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ", 1106 cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ",
974 direntry->d_name.name, attrs->ia_valid)); 1107 direntry->d_name.name, attrs->ia_valid));
975 cifs_sb = CIFS_SB(direntry->d_inode->i_sb); 1108 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
976 pTcon = cifs_sb->tcon; 1109 pTcon = cifs_sb->tcon;
@@ -1086,6 +1219,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1086 cifs_sb->mnt_cifs_flags & 1219 cifs_sb->mnt_cifs_flags &
1087 CIFS_MOUNT_MAP_SPECIAL_CHR); 1220 CIFS_MOUNT_MAP_SPECIAL_CHR);
1088 else if (attrs->ia_valid & ATTR_MODE) { 1221 else if (attrs->ia_valid & ATTR_MODE) {
1222 rc = 0;
1089 if ((mode & S_IWUGO) == 0) /* not writeable */ { 1223 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1090 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) 1224 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
1091 time_buf.Attributes = 1225 time_buf.Attributes =