diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-01 13:52:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-01 13:52:45 -0500 |
commit | 0f44bc36ba1cddbd34371110c4ef8f0800c8d465 (patch) | |
tree | ce5f664e91af8bc0988830acdacbba5080d9c5f3 | |
parent | efc518eb318c4d776933c23e7b82c2e5402b62de (diff) | |
parent | a9a315d41407cd1079eb815f4adae897cc08b0d2 (diff) |
Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French:
"A set of cifs fixes (mostly for symlinks, and SMB2 xattrs) and
cleanups"
* 'for-linus' of git://git.samba.org/sfrench/cifs-2.6:
cifs: Fix check for regular file in couldbe_mf_symlink()
[CIFS] Fix SMB2 mounts so they don't try to set or get xattrs via cifs
CIFS: Cleanup cifs open codepath
CIFS: Remove extra indentation in cifs_sfu_type
CIFS: Cleanup cifs_mknod
CIFS: Cleanup CIFSSMBOpen
cifs: Add support for follow_link on dfs shares under posix extensions
cifs: move unix extension call to cifs_query_symlink()
cifs: Re-order M-F Symlink code
cifs: Add create MFSymlinks to protocol ops struct
cifs: use protocol specific call for query_mf_symlink()
cifs: Rename MF symlink function names
cifs: Rename and cleanup open_query_close_cifs_symlink()
cifs: Fix memory leak in cifs_hardlink()
-rw-r--r-- | fs/cifs/cifsacl.c | 40 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 14 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 22 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 158 | ||||
-rw-r--r-- | fs/cifs/dir.c | 59 | ||||
-rw-r--r-- | fs/cifs/file.c | 2 | ||||
-rw-r--r-- | fs/cifs/inode.c | 178 | ||||
-rw-r--r-- | fs/cifs/link.c | 323 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb1ops.c | 126 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 49 |
11 files changed, 553 insertions, 420 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 51f5e0ee7237..8f9b4f710d4a 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -895,9 +895,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
895 | int oplock = 0; | 895 | int oplock = 0; |
896 | unsigned int xid; | 896 | unsigned int xid; |
897 | int rc, create_options = 0; | 897 | int rc, create_options = 0; |
898 | __u16 fid; | ||
899 | struct cifs_tcon *tcon; | 898 | struct cifs_tcon *tcon; |
900 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 899 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
900 | struct cifs_fid fid; | ||
901 | struct cifs_open_parms oparms; | ||
901 | 902 | ||
902 | if (IS_ERR(tlink)) | 903 | if (IS_ERR(tlink)) |
903 | return ERR_CAST(tlink); | 904 | return ERR_CAST(tlink); |
@@ -908,12 +909,19 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
908 | if (backup_cred(cifs_sb)) | 909 | if (backup_cred(cifs_sb)) |
909 | create_options |= CREATE_OPEN_BACKUP_INTENT; | 910 | create_options |= CREATE_OPEN_BACKUP_INTENT; |
910 | 911 | ||
911 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, | 912 | oparms.tcon = tcon; |
912 | create_options, &fid, &oplock, NULL, cifs_sb->local_nls, | 913 | oparms.cifs_sb = cifs_sb; |
913 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 914 | oparms.desired_access = READ_CONTROL; |
915 | oparms.create_options = create_options; | ||
916 | oparms.disposition = FILE_OPEN; | ||
917 | oparms.path = path; | ||
918 | oparms.fid = &fid; | ||
919 | oparms.reconnect = false; | ||
920 | |||
921 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
914 | if (!rc) { | 922 | if (!rc) { |
915 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); | 923 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen); |
916 | CIFSSMBClose(xid, tcon, fid); | 924 | CIFSSMBClose(xid, tcon, fid.netfid); |
917 | } | 925 | } |
918 | 926 | ||
919 | cifs_put_tlink(tlink); | 927 | cifs_put_tlink(tlink); |
@@ -950,10 +958,11 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
950 | int oplock = 0; | 958 | int oplock = 0; |
951 | unsigned int xid; | 959 | unsigned int xid; |
952 | int rc, access_flags, create_options = 0; | 960 | int rc, access_flags, create_options = 0; |
953 | __u16 fid; | ||
954 | struct cifs_tcon *tcon; | 961 | struct cifs_tcon *tcon; |
955 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 962 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
956 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 963 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
964 | struct cifs_fid fid; | ||
965 | struct cifs_open_parms oparms; | ||
957 | 966 | ||
958 | if (IS_ERR(tlink)) | 967 | if (IS_ERR(tlink)) |
959 | return PTR_ERR(tlink); | 968 | return PTR_ERR(tlink); |
@@ -969,18 +978,25 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
969 | else | 978 | else |
970 | access_flags = WRITE_DAC; | 979 | access_flags = WRITE_DAC; |
971 | 980 | ||
972 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags, | 981 | oparms.tcon = tcon; |
973 | create_options, &fid, &oplock, NULL, cifs_sb->local_nls, | 982 | oparms.cifs_sb = cifs_sb; |
974 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 983 | oparms.desired_access = access_flags; |
984 | oparms.create_options = create_options; | ||
985 | oparms.disposition = FILE_OPEN; | ||
986 | oparms.path = path; | ||
987 | oparms.fid = &fid; | ||
988 | oparms.reconnect = false; | ||
989 | |||
990 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
975 | if (rc) { | 991 | if (rc) { |
976 | cifs_dbg(VFS, "Unable to open file to set ACL\n"); | 992 | cifs_dbg(VFS, "Unable to open file to set ACL\n"); |
977 | goto out; | 993 | goto out; |
978 | } | 994 | } |
979 | 995 | ||
980 | rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag); | 996 | rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag); |
981 | cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc); | 997 | cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc); |
982 | 998 | ||
983 | CIFSSMBClose(xid, tcon, fid); | 999 | CIFSSMBClose(xid, tcon, fid.netfid); |
984 | out: | 1000 | out: |
985 | free_xid(xid); | 1001 | free_xid(xid); |
986 | cifs_put_tlink(tlink); | 1002 | cifs_put_tlink(tlink); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index f918a998a087..a245d1809ed8 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -370,8 +370,12 @@ struct smb_version_operations { | |||
370 | void (*new_lease_key)(struct cifs_fid *); | 370 | void (*new_lease_key)(struct cifs_fid *); |
371 | int (*generate_signingkey)(struct cifs_ses *); | 371 | int (*generate_signingkey)(struct cifs_ses *); |
372 | int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); | 372 | int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); |
373 | int (*query_mf_symlink)(const unsigned char *, char *, unsigned int *, | 373 | int (*query_mf_symlink)(unsigned int, struct cifs_tcon *, |
374 | struct cifs_sb_info *, unsigned int); | 374 | struct cifs_sb_info *, const unsigned char *, |
375 | char *, unsigned int *); | ||
376 | int (*create_mf_symlink)(unsigned int, struct cifs_tcon *, | ||
377 | struct cifs_sb_info *, const unsigned char *, | ||
378 | char *, unsigned int *); | ||
375 | /* if we can do cache read operations */ | 379 | /* if we can do cache read operations */ |
376 | bool (*is_read_op)(__u32); | 380 | bool (*is_read_op)(__u32); |
377 | /* set oplock level for the inode */ | 381 | /* set oplock level for the inode */ |
@@ -385,6 +389,12 @@ struct smb_version_operations { | |||
385 | struct cifsFileInfo *target_file, u64 src_off, u64 len, | 389 | struct cifsFileInfo *target_file, u64 src_off, u64 len, |
386 | u64 dest_off); | 390 | u64 dest_off); |
387 | int (*validate_negotiate)(const unsigned int, struct cifs_tcon *); | 391 | int (*validate_negotiate)(const unsigned int, struct cifs_tcon *); |
392 | ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *, | ||
393 | const unsigned char *, const unsigned char *, char *, | ||
394 | size_t, const struct nls_table *, int); | ||
395 | int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, | ||
396 | const char *, const void *, const __u16, | ||
397 | const struct nls_table *, int); | ||
388 | }; | 398 | }; |
389 | 399 | ||
390 | struct smb_version_values { | 400 | struct smb_version_values { |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 2c29db6a247e..79e6e9a93a8c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -362,11 +362,8 @@ extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, | |||
362 | const struct nls_table *nls_codepage); | 362 | const struct nls_table *nls_codepage); |
363 | extern int CIFSSMB_set_compression(const unsigned int xid, | 363 | extern int CIFSSMB_set_compression(const unsigned int xid, |
364 | struct cifs_tcon *tcon, __u16 fid); | 364 | struct cifs_tcon *tcon, __u16 fid); |
365 | extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, | 365 | extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, |
366 | const char *fileName, const int disposition, | 366 | int *oplock, FILE_ALL_INFO *buf); |
367 | const int access_flags, const int omode, | ||
368 | __u16 *netfid, int *pOplock, FILE_ALL_INFO *, | ||
369 | const struct nls_table *nls_codepage, int remap); | ||
370 | extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, | 367 | extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, |
371 | const char *fileName, const int disposition, | 368 | const char *fileName, const int disposition, |
372 | const int access_flags, const int omode, | 369 | const int access_flags, const int omode, |
@@ -476,8 +473,8 @@ extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon, | |||
476 | extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, | 473 | extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, |
477 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask); | 474 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask); |
478 | extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb); | 475 | extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb); |
479 | extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr); | 476 | extern bool couldbe_mf_symlink(const struct cifs_fattr *fattr); |
480 | extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, | 477 | extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, |
481 | struct cifs_sb_info *cifs_sb, | 478 | struct cifs_sb_info *cifs_sb, |
482 | struct cifs_fattr *fattr, | 479 | struct cifs_fattr *fattr, |
483 | const unsigned char *path); | 480 | const unsigned char *path); |
@@ -496,7 +493,12 @@ void cifs_writev_complete(struct work_struct *work); | |||
496 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, | 493 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, |
497 | work_func_t complete); | 494 | work_func_t complete); |
498 | void cifs_writedata_release(struct kref *refcount); | 495 | void cifs_writedata_release(struct kref *refcount); |
499 | int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, | 496 | int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, |
500 | unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, | 497 | struct cifs_sb_info *cifs_sb, |
501 | unsigned int xid); | 498 | const unsigned char *path, char *pbuf, |
499 | unsigned int *pbytes_read); | ||
500 | int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||
501 | struct cifs_sb_info *cifs_sb, | ||
502 | const unsigned char *path, char *pbuf, | ||
503 | unsigned int *pbytes_written); | ||
502 | #endif /* _CIFSPROTO_H */ | 504 | #endif /* _CIFSPROTO_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index d707edb6b852..4d881c35eeca 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1273,104 +1273,124 @@ OldOpenRetry: | |||
1273 | } | 1273 | } |
1274 | 1274 | ||
1275 | int | 1275 | int |
1276 | CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, | 1276 | CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, |
1277 | const char *fileName, const int openDisposition, | 1277 | FILE_ALL_INFO *buf) |
1278 | const int access_flags, const int create_options, __u16 *netfid, | ||
1279 | int *pOplock, FILE_ALL_INFO *pfile_info, | ||
1280 | const struct nls_table *nls_codepage, int remap) | ||
1281 | { | 1278 | { |
1282 | int rc = -EACCES; | 1279 | int rc = -EACCES; |
1283 | OPEN_REQ *pSMB = NULL; | 1280 | OPEN_REQ *req = NULL; |
1284 | OPEN_RSP *pSMBr = NULL; | 1281 | OPEN_RSP *rsp = NULL; |
1285 | int bytes_returned; | 1282 | int bytes_returned; |
1286 | int name_len; | 1283 | int name_len; |
1287 | __u16 count; | 1284 | __u16 count; |
1285 | struct cifs_sb_info *cifs_sb = oparms->cifs_sb; | ||
1286 | struct cifs_tcon *tcon = oparms->tcon; | ||
1287 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
1288 | const struct nls_table *nls = cifs_sb->local_nls; | ||
1289 | int create_options = oparms->create_options; | ||
1290 | int desired_access = oparms->desired_access; | ||
1291 | int disposition = oparms->disposition; | ||
1292 | const char *path = oparms->path; | ||
1288 | 1293 | ||
1289 | openRetry: | 1294 | openRetry: |
1290 | rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB, | 1295 | rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req, |
1291 | (void **) &pSMBr); | 1296 | (void **)&rsp); |
1292 | if (rc) | 1297 | if (rc) |
1293 | return rc; | 1298 | return rc; |
1294 | 1299 | ||
1295 | pSMB->AndXCommand = 0xFF; /* none */ | 1300 | /* no commands go after this */ |
1301 | req->AndXCommand = 0xFF; | ||
1296 | 1302 | ||
1297 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1303 | if (req->hdr.Flags2 & SMBFLG2_UNICODE) { |
1298 | count = 1; /* account for one byte pad to word boundary */ | 1304 | /* account for one byte pad to word boundary */ |
1299 | name_len = | 1305 | count = 1; |
1300 | cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1), | 1306 | name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1), |
1301 | fileName, PATH_MAX, nls_codepage, remap); | 1307 | path, PATH_MAX, nls, remap); |
1302 | name_len++; /* trailing null */ | 1308 | /* trailing null */ |
1309 | name_len++; | ||
1303 | name_len *= 2; | 1310 | name_len *= 2; |
1304 | pSMB->NameLength = cpu_to_le16(name_len); | 1311 | req->NameLength = cpu_to_le16(name_len); |
1305 | } else { /* BB improve check for buffer overruns BB */ | 1312 | } else { |
1306 | count = 0; /* no pad */ | 1313 | /* BB improve check for buffer overruns BB */ |
1307 | name_len = strnlen(fileName, PATH_MAX); | 1314 | /* no pad */ |
1308 | name_len++; /* trailing null */ | 1315 | count = 0; |
1309 | pSMB->NameLength = cpu_to_le16(name_len); | 1316 | name_len = strnlen(path, PATH_MAX); |
1310 | strncpy(pSMB->fileName, fileName, name_len); | 1317 | /* trailing null */ |
1318 | name_len++; | ||
1319 | req->NameLength = cpu_to_le16(name_len); | ||
1320 | strncpy(req->fileName, path, name_len); | ||
1311 | } | 1321 | } |
1312 | if (*pOplock & REQ_OPLOCK) | 1322 | |
1313 | pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); | 1323 | if (*oplock & REQ_OPLOCK) |
1314 | else if (*pOplock & REQ_BATCHOPLOCK) | 1324 | req->OpenFlags = cpu_to_le32(REQ_OPLOCK); |
1315 | pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); | 1325 | else if (*oplock & REQ_BATCHOPLOCK) |
1316 | pSMB->DesiredAccess = cpu_to_le32(access_flags); | 1326 | req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); |
1317 | pSMB->AllocationSize = 0; | 1327 | |
1318 | /* set file as system file if special file such | 1328 | req->DesiredAccess = cpu_to_le32(desired_access); |
1319 | as fifo and server expecting SFU style and | 1329 | req->AllocationSize = 0; |
1320 | no Unix extensions */ | 1330 | |
1331 | /* | ||
1332 | * Set file as system file if special file such as fifo and server | ||
1333 | * expecting SFU style and no Unix extensions. | ||
1334 | */ | ||
1321 | if (create_options & CREATE_OPTION_SPECIAL) | 1335 | if (create_options & CREATE_OPTION_SPECIAL) |
1322 | pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); | 1336 | req->FileAttributes = cpu_to_le32(ATTR_SYSTEM); |
1323 | else | 1337 | else |
1324 | pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); | 1338 | req->FileAttributes = cpu_to_le32(ATTR_NORMAL); |
1325 | 1339 | ||
1326 | /* XP does not handle ATTR_POSIX_SEMANTICS */ | 1340 | /* |
1327 | /* but it helps speed up case sensitive checks for other | 1341 | * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case |
1328 | servers such as Samba */ | 1342 | * sensitive checks for other servers such as Samba. |
1343 | */ | ||
1329 | if (tcon->ses->capabilities & CAP_UNIX) | 1344 | if (tcon->ses->capabilities & CAP_UNIX) |
1330 | pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); | 1345 | req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); |
1331 | 1346 | ||
1332 | if (create_options & CREATE_OPTION_READONLY) | 1347 | if (create_options & CREATE_OPTION_READONLY) |
1333 | pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY); | 1348 | req->FileAttributes |= cpu_to_le32(ATTR_READONLY); |
1349 | |||
1350 | req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); | ||
1351 | req->CreateDisposition = cpu_to_le32(disposition); | ||
1352 | req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); | ||
1334 | 1353 | ||
1335 | pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); | ||
1336 | pSMB->CreateDisposition = cpu_to_le32(openDisposition); | ||
1337 | pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); | ||
1338 | /* BB Expirement with various impersonation levels and verify */ | 1354 | /* BB Expirement with various impersonation levels and verify */ |
1339 | pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); | 1355 | req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); |
1340 | pSMB->SecurityFlags = | 1356 | req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY; |
1341 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; | ||
1342 | 1357 | ||
1343 | count += name_len; | 1358 | count += name_len; |
1344 | inc_rfc1001_len(pSMB, count); | 1359 | inc_rfc1001_len(req, count); |
1345 | 1360 | ||
1346 | pSMB->ByteCount = cpu_to_le16(count); | 1361 | req->ByteCount = cpu_to_le16(count); |
1347 | /* long_op set to 1 to allow for oplock break timeouts */ | 1362 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req, |
1348 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1363 | (struct smb_hdr *)rsp, &bytes_returned, 0); |
1349 | (struct smb_hdr *)pSMBr, &bytes_returned, 0); | ||
1350 | cifs_stats_inc(&tcon->stats.cifs_stats.num_opens); | 1364 | cifs_stats_inc(&tcon->stats.cifs_stats.num_opens); |
1351 | if (rc) { | 1365 | if (rc) { |
1352 | cifs_dbg(FYI, "Error in Open = %d\n", rc); | 1366 | cifs_dbg(FYI, "Error in Open = %d\n", rc); |
1353 | } else { | 1367 | cifs_buf_release(req); |
1354 | *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */ | 1368 | if (rc == -EAGAIN) |
1355 | *netfid = pSMBr->Fid; /* cifs fid stays in le */ | 1369 | goto openRetry; |
1356 | /* Let caller know file was created so we can set the mode. */ | 1370 | return rc; |
1357 | /* Do we care about the CreateAction in any other cases? */ | ||
1358 | if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction) | ||
1359 | *pOplock |= CIFS_CREATE_ACTION; | ||
1360 | if (pfile_info) { | ||
1361 | memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime, | ||
1362 | 36 /* CreationTime to Attributes */); | ||
1363 | /* the file_info buf is endian converted by caller */ | ||
1364 | pfile_info->AllocationSize = pSMBr->AllocationSize; | ||
1365 | pfile_info->EndOfFile = pSMBr->EndOfFile; | ||
1366 | pfile_info->NumberOfLinks = cpu_to_le32(1); | ||
1367 | pfile_info->DeletePending = 0; | ||
1368 | } | ||
1369 | } | 1371 | } |
1370 | 1372 | ||
1371 | cifs_buf_release(pSMB); | 1373 | /* 1 byte no need to le_to_cpu */ |
1372 | if (rc == -EAGAIN) | 1374 | *oplock = rsp->OplockLevel; |
1373 | goto openRetry; | 1375 | /* cifs fid stays in le */ |
1376 | oparms->fid->netfid = rsp->Fid; | ||
1377 | |||
1378 | /* Let caller know file was created so we can set the mode. */ | ||
1379 | /* Do we care about the CreateAction in any other cases? */ | ||
1380 | if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction) | ||
1381 | *oplock |= CIFS_CREATE_ACTION; | ||
1382 | |||
1383 | if (buf) { | ||
1384 | /* copy from CreationTime to Attributes */ | ||
1385 | memcpy((char *)buf, (char *)&rsp->CreationTime, 36); | ||
1386 | /* the file_info buf is endian converted by caller */ | ||
1387 | buf->AllocationSize = rsp->AllocationSize; | ||
1388 | buf->EndOfFile = rsp->EndOfFile; | ||
1389 | buf->NumberOfLinks = cpu_to_le32(1); | ||
1390 | buf->DeletePending = 0; | ||
1391 | } | ||
1392 | |||
1393 | cifs_buf_release(req); | ||
1374 | return rc; | 1394 | return rc; |
1375 | } | 1395 | } |
1376 | 1396 | ||
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index a514e0a65f69..d3a6796caa5a 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -565,12 +565,13 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
565 | int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; | 565 | int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; |
566 | struct cifs_sb_info *cifs_sb; | 566 | struct cifs_sb_info *cifs_sb; |
567 | struct tcon_link *tlink; | 567 | struct tcon_link *tlink; |
568 | struct cifs_tcon *pTcon; | 568 | struct cifs_tcon *tcon; |
569 | struct cifs_io_parms io_parms; | 569 | struct cifs_io_parms io_parms; |
570 | char *full_path = NULL; | 570 | char *full_path = NULL; |
571 | struct inode *newinode = NULL; | 571 | struct inode *newinode = NULL; |
572 | int oplock = 0; | 572 | int oplock = 0; |
573 | u16 fileHandle; | 573 | struct cifs_fid fid; |
574 | struct cifs_open_parms oparms; | ||
574 | FILE_ALL_INFO *buf = NULL; | 575 | FILE_ALL_INFO *buf = NULL; |
575 | unsigned int bytes_written; | 576 | unsigned int bytes_written; |
576 | struct win_dev *pdev; | 577 | struct win_dev *pdev; |
@@ -583,7 +584,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
583 | if (IS_ERR(tlink)) | 584 | if (IS_ERR(tlink)) |
584 | return PTR_ERR(tlink); | 585 | return PTR_ERR(tlink); |
585 | 586 | ||
586 | pTcon = tlink_tcon(tlink); | 587 | tcon = tlink_tcon(tlink); |
587 | 588 | ||
588 | xid = get_xid(); | 589 | xid = get_xid(); |
589 | 590 | ||
@@ -593,7 +594,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
593 | goto mknod_out; | 594 | goto mknod_out; |
594 | } | 595 | } |
595 | 596 | ||
596 | if (pTcon->unix_ext) { | 597 | if (tcon->unix_ext) { |
597 | struct cifs_unix_set_info_args args = { | 598 | struct cifs_unix_set_info_args args = { |
598 | .mode = mode & ~current_umask(), | 599 | .mode = mode & ~current_umask(), |
599 | .ctime = NO_CHANGE_64, | 600 | .ctime = NO_CHANGE_64, |
@@ -608,7 +609,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
608 | args.uid = INVALID_UID; /* no change */ | 609 | args.uid = INVALID_UID; /* no change */ |
609 | args.gid = INVALID_GID; /* no change */ | 610 | args.gid = INVALID_GID; /* no change */ |
610 | } | 611 | } |
611 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, | 612 | rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, |
612 | cifs_sb->local_nls, | 613 | cifs_sb->local_nls, |
613 | cifs_sb->mnt_cifs_flags & | 614 | cifs_sb->mnt_cifs_flags & |
614 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 615 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -640,42 +641,44 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
640 | if (backup_cred(cifs_sb)) | 641 | if (backup_cred(cifs_sb)) |
641 | create_options |= CREATE_OPEN_BACKUP_INTENT; | 642 | create_options |= CREATE_OPEN_BACKUP_INTENT; |
642 | 643 | ||
643 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, | 644 | oparms.tcon = tcon; |
644 | GENERIC_WRITE, create_options, | 645 | oparms.cifs_sb = cifs_sb; |
645 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 646 | oparms.desired_access = GENERIC_WRITE; |
646 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 647 | oparms.create_options = create_options; |
648 | oparms.disposition = FILE_CREATE; | ||
649 | oparms.path = full_path; | ||
650 | oparms.fid = &fid; | ||
651 | oparms.reconnect = false; | ||
652 | |||
653 | rc = CIFS_open(xid, &oparms, &oplock, buf); | ||
647 | if (rc) | 654 | if (rc) |
648 | goto mknod_out; | 655 | goto mknod_out; |
649 | 656 | ||
650 | /* BB Do not bother to decode buf since no local inode yet to put | 657 | /* |
651 | * timestamps in, but we can reuse it safely */ | 658 | * BB Do not bother to decode buf since no local inode yet to put |
659 | * timestamps in, but we can reuse it safely. | ||
660 | */ | ||
652 | 661 | ||
653 | pdev = (struct win_dev *)buf; | 662 | pdev = (struct win_dev *)buf; |
654 | io_parms.netfid = fileHandle; | 663 | io_parms.netfid = fid.netfid; |
655 | io_parms.pid = current->tgid; | 664 | io_parms.pid = current->tgid; |
656 | io_parms.tcon = pTcon; | 665 | io_parms.tcon = tcon; |
657 | io_parms.offset = 0; | 666 | io_parms.offset = 0; |
658 | io_parms.length = sizeof(struct win_dev); | 667 | io_parms.length = sizeof(struct win_dev); |
659 | if (S_ISCHR(mode)) { | 668 | if (S_ISCHR(mode)) { |
660 | memcpy(pdev->type, "IntxCHR", 8); | 669 | memcpy(pdev->type, "IntxCHR", 8); |
661 | pdev->major = | 670 | pdev->major = cpu_to_le64(MAJOR(device_number)); |
662 | cpu_to_le64(MAJOR(device_number)); | 671 | pdev->minor = cpu_to_le64(MINOR(device_number)); |
663 | pdev->minor = | 672 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, |
664 | cpu_to_le64(MINOR(device_number)); | 673 | NULL, 0); |
665 | rc = CIFSSMBWrite(xid, &io_parms, | ||
666 | &bytes_written, (char *)pdev, | ||
667 | NULL, 0); | ||
668 | } else if (S_ISBLK(mode)) { | 674 | } else if (S_ISBLK(mode)) { |
669 | memcpy(pdev->type, "IntxBLK", 8); | 675 | memcpy(pdev->type, "IntxBLK", 8); |
670 | pdev->major = | 676 | pdev->major = cpu_to_le64(MAJOR(device_number)); |
671 | cpu_to_le64(MAJOR(device_number)); | 677 | pdev->minor = cpu_to_le64(MINOR(device_number)); |
672 | pdev->minor = | 678 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, |
673 | cpu_to_le64(MINOR(device_number)); | 679 | NULL, 0); |
674 | rc = CIFSSMBWrite(xid, &io_parms, | ||
675 | &bytes_written, (char *)pdev, | ||
676 | NULL, 0); | ||
677 | } /* else if (S_ISFIFO) */ | 680 | } /* else if (S_ISFIFO) */ |
678 | CIFSSMBClose(xid, pTcon, fileHandle); | 681 | CIFSSMBClose(xid, tcon, fid.netfid); |
679 | d_drop(direntry); | 682 | d_drop(direntry); |
680 | 683 | ||
681 | /* FIXME: add code here to set EAs */ | 684 | /* FIXME: add code here to set EAs */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5a5a87240fe2..853d6d1cc822 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -678,7 +678,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) | |||
678 | 678 | ||
679 | /* | 679 | /* |
680 | * Can not refresh inode by passing in file_info buf to be returned by | 680 | * Can not refresh inode by passing in file_info buf to be returned by |
681 | * CIFSSMBOpen and then calling get_inode_info with returned buf since | 681 | * ops->open and then calling get_inode_info with returned buf since |
682 | * file might have write behind data that needs to be flushed and server | 682 | * file might have write behind data that needs to be flushed and server |
683 | * version of file size can be stale. If we knew for sure that inode was | 683 | * version of file size can be stale. If we knew for sure that inode was |
684 | * not dirty locally we could do this. | 684 | * not dirty locally we could do this. |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 49719b8228e5..9cb9679d7357 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -383,10 +383,10 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
383 | 383 | ||
384 | /* check for Minshall+French symlinks */ | 384 | /* check for Minshall+French symlinks */ |
385 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | 385 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { |
386 | int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, | 386 | int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr, |
387 | full_path); | 387 | full_path); |
388 | if (tmprc) | 388 | if (tmprc) |
389 | cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); | 389 | cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); |
390 | } | 390 | } |
391 | 391 | ||
392 | if (*pinode == NULL) { | 392 | if (*pinode == NULL) { |
@@ -404,18 +404,20 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
404 | } | 404 | } |
405 | 405 | ||
406 | static int | 406 | static int |
407 | cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | 407 | cifs_sfu_type(struct cifs_fattr *fattr, const char *path, |
408 | struct cifs_sb_info *cifs_sb, unsigned int xid) | 408 | struct cifs_sb_info *cifs_sb, unsigned int xid) |
409 | { | 409 | { |
410 | int rc; | 410 | int rc; |
411 | int oplock = 0; | 411 | int oplock = 0; |
412 | __u16 netfid; | ||
413 | struct tcon_link *tlink; | 412 | struct tcon_link *tlink; |
414 | struct cifs_tcon *tcon; | 413 | struct cifs_tcon *tcon; |
414 | struct cifs_fid fid; | ||
415 | struct cifs_open_parms oparms; | ||
415 | struct cifs_io_parms io_parms; | 416 | struct cifs_io_parms io_parms; |
416 | char buf[24]; | 417 | char buf[24]; |
417 | unsigned int bytes_read; | 418 | unsigned int bytes_read; |
418 | char *pbuf; | 419 | char *pbuf; |
420 | int buf_type = CIFS_NO_BUFFER; | ||
419 | 421 | ||
420 | pbuf = buf; | 422 | pbuf = buf; |
421 | 423 | ||
@@ -436,62 +438,69 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
436 | return PTR_ERR(tlink); | 438 | return PTR_ERR(tlink); |
437 | tcon = tlink_tcon(tlink); | 439 | tcon = tlink_tcon(tlink); |
438 | 440 | ||
439 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, | 441 | oparms.tcon = tcon; |
440 | CREATE_NOT_DIR, &netfid, &oplock, NULL, | 442 | oparms.cifs_sb = cifs_sb; |
441 | cifs_sb->local_nls, | 443 | oparms.desired_access = GENERIC_READ; |
442 | cifs_sb->mnt_cifs_flags & | 444 | oparms.create_options = CREATE_NOT_DIR; |
443 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 445 | oparms.disposition = FILE_OPEN; |
444 | if (rc == 0) { | 446 | oparms.path = path; |
445 | int buf_type = CIFS_NO_BUFFER; | 447 | oparms.fid = &fid; |
446 | /* Read header */ | 448 | oparms.reconnect = false; |
447 | io_parms.netfid = netfid; | 449 | |
448 | io_parms.pid = current->tgid; | 450 | rc = CIFS_open(xid, &oparms, &oplock, NULL); |
449 | io_parms.tcon = tcon; | 451 | if (rc) { |
450 | io_parms.offset = 0; | 452 | cifs_put_tlink(tlink); |
451 | io_parms.length = 24; | 453 | return rc; |
452 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, | 454 | } |
453 | &buf_type); | 455 | |
454 | if ((rc == 0) && (bytes_read >= 8)) { | 456 | /* Read header */ |
455 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 457 | io_parms.netfid = fid.netfid; |
456 | cifs_dbg(FYI, "Block device\n"); | 458 | io_parms.pid = current->tgid; |
457 | fattr->cf_mode |= S_IFBLK; | 459 | io_parms.tcon = tcon; |
458 | fattr->cf_dtype = DT_BLK; | 460 | io_parms.offset = 0; |
459 | if (bytes_read == 24) { | 461 | io_parms.length = 24; |
460 | /* we have enough to decode dev num */ | 462 | |
461 | __u64 mjr; /* major */ | 463 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); |
462 | __u64 mnr; /* minor */ | 464 | if ((rc == 0) && (bytes_read >= 8)) { |
463 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 465 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
464 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 466 | cifs_dbg(FYI, "Block device\n"); |
465 | fattr->cf_rdev = MKDEV(mjr, mnr); | 467 | fattr->cf_mode |= S_IFBLK; |
466 | } | 468 | fattr->cf_dtype = DT_BLK; |
467 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | 469 | if (bytes_read == 24) { |
468 | cifs_dbg(FYI, "Char device\n"); | 470 | /* we have enough to decode dev num */ |
469 | fattr->cf_mode |= S_IFCHR; | 471 | __u64 mjr; /* major */ |
470 | fattr->cf_dtype = DT_CHR; | 472 | __u64 mnr; /* minor */ |
471 | if (bytes_read == 24) { | 473 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
472 | /* we have enough to decode dev num */ | 474 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
473 | __u64 mjr; /* major */ | 475 | fattr->cf_rdev = MKDEV(mjr, mnr); |
474 | __u64 mnr; /* minor */ | ||
475 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | ||
476 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | ||
477 | fattr->cf_rdev = MKDEV(mjr, mnr); | ||
478 | } | ||
479 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | ||
480 | cifs_dbg(FYI, "Symlink\n"); | ||
481 | fattr->cf_mode |= S_IFLNK; | ||
482 | fattr->cf_dtype = DT_LNK; | ||
483 | } else { | ||
484 | fattr->cf_mode |= S_IFREG; /* file? */ | ||
485 | fattr->cf_dtype = DT_REG; | ||
486 | rc = -EOPNOTSUPP; | ||
487 | } | 476 | } |
477 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | ||
478 | cifs_dbg(FYI, "Char device\n"); | ||
479 | fattr->cf_mode |= S_IFCHR; | ||
480 | fattr->cf_dtype = DT_CHR; | ||
481 | if (bytes_read == 24) { | ||
482 | /* we have enough to decode dev num */ | ||
483 | __u64 mjr; /* major */ | ||
484 | __u64 mnr; /* minor */ | ||
485 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | ||
486 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | ||
487 | fattr->cf_rdev = MKDEV(mjr, mnr); | ||
488 | } | ||
489 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | ||
490 | cifs_dbg(FYI, "Symlink\n"); | ||
491 | fattr->cf_mode |= S_IFLNK; | ||
492 | fattr->cf_dtype = DT_LNK; | ||
488 | } else { | 493 | } else { |
489 | fattr->cf_mode |= S_IFREG; /* then it is a file */ | 494 | fattr->cf_mode |= S_IFREG; /* file? */ |
490 | fattr->cf_dtype = DT_REG; | 495 | fattr->cf_dtype = DT_REG; |
491 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 496 | rc = -EOPNOTSUPP; |
492 | } | 497 | } |
493 | CIFSSMBClose(xid, tcon, netfid); | 498 | } else { |
499 | fattr->cf_mode |= S_IFREG; /* then it is a file */ | ||
500 | fattr->cf_dtype = DT_REG; | ||
501 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | ||
494 | } | 502 | } |
503 | CIFSSMBClose(xid, tcon, fid.netfid); | ||
495 | cifs_put_tlink(tlink); | 504 | cifs_put_tlink(tlink); |
496 | return rc; | 505 | return rc; |
497 | } | 506 | } |
@@ -800,10 +809,10 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
800 | 809 | ||
801 | /* check for Minshall+French symlinks */ | 810 | /* check for Minshall+French symlinks */ |
802 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | 811 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { |
803 | tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, | 812 | tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr, |
804 | full_path); | 813 | full_path); |
805 | if (tmprc) | 814 | if (tmprc) |
806 | cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); | 815 | cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); |
807 | } | 816 | } |
808 | 817 | ||
809 | if (!*inode) { | 818 | if (!*inode) { |
@@ -1032,7 +1041,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1032 | { | 1041 | { |
1033 | int oplock = 0; | 1042 | int oplock = 0; |
1034 | int rc; | 1043 | int rc; |
1035 | __u16 netfid; | 1044 | struct cifs_fid fid; |
1045 | struct cifs_open_parms oparms; | ||
1036 | struct inode *inode = dentry->d_inode; | 1046 | struct inode *inode = dentry->d_inode; |
1037 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1047 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1038 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1048 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
@@ -1055,10 +1065,16 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1055 | goto out; | 1065 | goto out; |
1056 | } | 1066 | } |
1057 | 1067 | ||
1058 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 1068 | oparms.tcon = tcon; |
1059 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, | 1069 | oparms.cifs_sb = cifs_sb; |
1060 | &netfid, &oplock, NULL, cifs_sb->local_nls, | 1070 | oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES; |
1061 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1071 | oparms.create_options = CREATE_NOT_DIR; |
1072 | oparms.disposition = FILE_OPEN; | ||
1073 | oparms.path = full_path; | ||
1074 | oparms.fid = &fid; | ||
1075 | oparms.reconnect = false; | ||
1076 | |||
1077 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
1062 | if (rc != 0) | 1078 | if (rc != 0) |
1063 | goto out; | 1079 | goto out; |
1064 | 1080 | ||
@@ -1079,7 +1095,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1079 | goto out_close; | 1095 | goto out_close; |
1080 | } | 1096 | } |
1081 | info_buf->Attributes = cpu_to_le32(dosattr); | 1097 | info_buf->Attributes = cpu_to_le32(dosattr); |
1082 | rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, | 1098 | rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid, |
1083 | current->tgid); | 1099 | current->tgid); |
1084 | /* although we would like to mark the file hidden | 1100 | /* although we would like to mark the file hidden |
1085 | if that fails we will still try to rename it */ | 1101 | if that fails we will still try to rename it */ |
@@ -1090,7 +1106,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1090 | } | 1106 | } |
1091 | 1107 | ||
1092 | /* rename the file */ | 1108 | /* rename the file */ |
1093 | rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, | 1109 | rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL, |
1110 | cifs_sb->local_nls, | ||
1094 | cifs_sb->mnt_cifs_flags & | 1111 | cifs_sb->mnt_cifs_flags & |
1095 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1112 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1096 | if (rc != 0) { | 1113 | if (rc != 0) { |
@@ -1100,7 +1117,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1100 | 1117 | ||
1101 | /* try to set DELETE_ON_CLOSE */ | 1118 | /* try to set DELETE_ON_CLOSE */ |
1102 | if (!cifsInode->delete_pending) { | 1119 | if (!cifsInode->delete_pending) { |
1103 | rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid, | 1120 | rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid, |
1104 | current->tgid); | 1121 | current->tgid); |
1105 | /* | 1122 | /* |
1106 | * some samba versions return -ENOENT when we try to set the | 1123 | * some samba versions return -ENOENT when we try to set the |
@@ -1120,7 +1137,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1120 | } | 1137 | } |
1121 | 1138 | ||
1122 | out_close: | 1139 | out_close: |
1123 | CIFSSMBClose(xid, tcon, netfid); | 1140 | CIFSSMBClose(xid, tcon, fid.netfid); |
1124 | out: | 1141 | out: |
1125 | kfree(info_buf); | 1142 | kfree(info_buf); |
1126 | cifs_put_tlink(tlink); | 1143 | cifs_put_tlink(tlink); |
@@ -1132,13 +1149,13 @@ out: | |||
1132 | * them anyway. | 1149 | * them anyway. |
1133 | */ | 1150 | */ |
1134 | undo_rename: | 1151 | undo_rename: |
1135 | CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name, | 1152 | CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name, |
1136 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1153 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
1137 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1154 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1138 | undo_setattr: | 1155 | undo_setattr: |
1139 | if (dosattr != origattr) { | 1156 | if (dosattr != origattr) { |
1140 | info_buf->Attributes = cpu_to_le32(origattr); | 1157 | info_buf->Attributes = cpu_to_le32(origattr); |
1141 | if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, | 1158 | if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid, |
1142 | current->tgid)) | 1159 | current->tgid)) |
1143 | cifsInode->cifsAttrs = origattr; | 1160 | cifsInode->cifsAttrs = origattr; |
1144 | } | 1161 | } |
@@ -1549,7 +1566,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, | |||
1549 | struct tcon_link *tlink; | 1566 | struct tcon_link *tlink; |
1550 | struct cifs_tcon *tcon; | 1567 | struct cifs_tcon *tcon; |
1551 | struct TCP_Server_Info *server; | 1568 | struct TCP_Server_Info *server; |
1552 | __u16 srcfid; | 1569 | struct cifs_fid fid; |
1570 | struct cifs_open_parms oparms; | ||
1553 | int oplock, rc; | 1571 | int oplock, rc; |
1554 | 1572 | ||
1555 | tlink = cifs_sb_tlink(cifs_sb); | 1573 | tlink = cifs_sb_tlink(cifs_sb); |
@@ -1576,17 +1594,23 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, | |||
1576 | if (to_dentry->d_parent != from_dentry->d_parent) | 1594 | if (to_dentry->d_parent != from_dentry->d_parent) |
1577 | goto do_rename_exit; | 1595 | goto do_rename_exit; |
1578 | 1596 | ||
1597 | oparms.tcon = tcon; | ||
1598 | oparms.cifs_sb = cifs_sb; | ||
1579 | /* open the file to be renamed -- we need DELETE perms */ | 1599 | /* open the file to be renamed -- we need DELETE perms */ |
1580 | rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE, | 1600 | oparms.desired_access = DELETE; |
1581 | CREATE_NOT_DIR, &srcfid, &oplock, NULL, | 1601 | oparms.create_options = CREATE_NOT_DIR; |
1582 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1602 | oparms.disposition = FILE_OPEN; |
1583 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1603 | oparms.path = from_path; |
1604 | oparms.fid = &fid; | ||
1605 | oparms.reconnect = false; | ||
1606 | |||
1607 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
1584 | if (rc == 0) { | 1608 | if (rc == 0) { |
1585 | rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid, | 1609 | rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, |
1586 | (const char *) to_dentry->d_name.name, | 1610 | (const char *) to_dentry->d_name.name, |
1587 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1611 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
1588 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1612 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1589 | CIFSSMBClose(xid, tcon, srcfid); | 1613 | CIFSSMBClose(xid, tcon, fid.netfid); |
1590 | } | 1614 | } |
1591 | do_rename_exit: | 1615 | do_rename_exit: |
1592 | cifs_put_tlink(tlink); | 1616 | cifs_put_tlink(tlink); |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 92aee08483a5..264ece71bdb2 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -29,6 +29,10 @@ | |||
29 | #include "cifs_debug.h" | 29 | #include "cifs_debug.h" |
30 | #include "cifs_fs_sb.h" | 30 | #include "cifs_fs_sb.h" |
31 | 31 | ||
32 | /* | ||
33 | * M-F Symlink Functions - Begin | ||
34 | */ | ||
35 | |||
32 | #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) | 36 | #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) |
33 | #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) | 37 | #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) |
34 | #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1)) | 38 | #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1)) |
@@ -91,10 +95,8 @@ symlink_hash_err: | |||
91 | } | 95 | } |
92 | 96 | ||
93 | static int | 97 | static int |
94 | CIFSParseMFSymlink(const u8 *buf, | 98 | parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len, |
95 | unsigned int buf_len, | 99 | char **_link_str) |
96 | unsigned int *_link_len, | ||
97 | char **_link_str) | ||
98 | { | 100 | { |
99 | int rc; | 101 | int rc; |
100 | unsigned int link_len; | 102 | unsigned int link_len; |
@@ -137,7 +139,7 @@ CIFSParseMFSymlink(const u8 *buf, | |||
137 | } | 139 | } |
138 | 140 | ||
139 | static int | 141 | static int |
140 | CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) | 142 | format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str) |
141 | { | 143 | { |
142 | int rc; | 144 | int rc; |
143 | unsigned int link_len; | 145 | unsigned int link_len; |
@@ -180,190 +182,94 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) | |||
180 | return 0; | 182 | return 0; |
181 | } | 183 | } |
182 | 184 | ||
185 | bool | ||
186 | couldbe_mf_symlink(const struct cifs_fattr *fattr) | ||
187 | { | ||
188 | if (!S_ISREG(fattr->cf_mode)) | ||
189 | /* it's not a symlink */ | ||
190 | return false; | ||
191 | |||
192 | if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) | ||
193 | /* it's not a symlink */ | ||
194 | return false; | ||
195 | |||
196 | return true; | ||
197 | } | ||
198 | |||
183 | static int | 199 | static int |
184 | CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, | 200 | create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, |
185 | const char *fromName, const char *toName, | 201 | struct cifs_sb_info *cifs_sb, const char *fromName, |
186 | struct cifs_sb_info *cifs_sb) | 202 | const char *toName) |
187 | { | 203 | { |
188 | int rc; | 204 | int rc; |
189 | int oplock = 0; | ||
190 | int remap; | ||
191 | int create_options = CREATE_NOT_DIR; | ||
192 | __u16 netfid = 0; | ||
193 | u8 *buf; | 205 | u8 *buf; |
194 | unsigned int bytes_written = 0; | 206 | unsigned int bytes_written = 0; |
195 | struct cifs_io_parms io_parms; | ||
196 | struct nls_table *nls_codepage; | ||
197 | |||
198 | nls_codepage = cifs_sb->local_nls; | ||
199 | remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
200 | 207 | ||
201 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); | 208 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); |
202 | if (!buf) | 209 | if (!buf) |
203 | return -ENOMEM; | 210 | return -ENOMEM; |
204 | 211 | ||
205 | rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); | 212 | rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); |
206 | if (rc != 0) { | 213 | if (rc) |
207 | kfree(buf); | 214 | goto out; |
208 | return rc; | ||
209 | } | ||
210 | |||
211 | if (backup_cred(cifs_sb)) | ||
212 | create_options |= CREATE_OPEN_BACKUP_INTENT; | ||
213 | |||
214 | rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE, | ||
215 | create_options, &netfid, &oplock, NULL, | ||
216 | nls_codepage, remap); | ||
217 | if (rc != 0) { | ||
218 | kfree(buf); | ||
219 | return rc; | ||
220 | } | ||
221 | |||
222 | io_parms.netfid = netfid; | ||
223 | io_parms.pid = current->tgid; | ||
224 | io_parms.tcon = tcon; | ||
225 | io_parms.offset = 0; | ||
226 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
227 | 215 | ||
228 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0); | 216 | rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb, |
229 | CIFSSMBClose(xid, tcon, netfid); | 217 | fromName, buf, &bytes_written); |
230 | kfree(buf); | 218 | if (rc) |
231 | if (rc != 0) | 219 | goto out; |
232 | return rc; | ||
233 | 220 | ||
234 | if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE) | 221 | if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE) |
235 | return -EIO; | 222 | rc = -EIO; |
236 | 223 | out: | |
237 | return 0; | 224 | kfree(buf); |
225 | return rc; | ||
238 | } | 226 | } |
239 | 227 | ||
240 | static int | 228 | static int |
241 | CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, | 229 | query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, |
242 | const unsigned char *searchName, char **symlinkinfo, | 230 | struct cifs_sb_info *cifs_sb, const unsigned char *path, |
243 | const struct nls_table *nls_codepage, int remap) | 231 | char **symlinkinfo) |
244 | { | 232 | { |
245 | int rc; | 233 | int rc; |
246 | int oplock = 0; | 234 | u8 *buf = NULL; |
247 | __u16 netfid = 0; | ||
248 | u8 *buf; | ||
249 | char *pbuf; | ||
250 | unsigned int bytes_read = 0; | ||
251 | int buf_type = CIFS_NO_BUFFER; | ||
252 | unsigned int link_len = 0; | 235 | unsigned int link_len = 0; |
253 | struct cifs_io_parms io_parms; | 236 | unsigned int bytes_read = 0; |
254 | FILE_ALL_INFO file_info; | ||
255 | |||
256 | rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ, | ||
257 | CREATE_NOT_DIR, &netfid, &oplock, &file_info, | ||
258 | nls_codepage, remap); | ||
259 | if (rc != 0) | ||
260 | return rc; | ||
261 | |||
262 | if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { | ||
263 | CIFSSMBClose(xid, tcon, netfid); | ||
264 | /* it's not a symlink */ | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | 237 | ||
268 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); | 238 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); |
269 | if (!buf) | 239 | if (!buf) |
270 | return -ENOMEM; | 240 | return -ENOMEM; |
271 | pbuf = buf; | ||
272 | io_parms.netfid = netfid; | ||
273 | io_parms.pid = current->tgid; | ||
274 | io_parms.tcon = tcon; | ||
275 | io_parms.offset = 0; | ||
276 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
277 | |||
278 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); | ||
279 | CIFSSMBClose(xid, tcon, netfid); | ||
280 | if (rc != 0) { | ||
281 | kfree(buf); | ||
282 | return rc; | ||
283 | } | ||
284 | |||
285 | rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo); | ||
286 | kfree(buf); | ||
287 | if (rc != 0) | ||
288 | return rc; | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | bool | ||
294 | CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr) | ||
295 | { | ||
296 | if (!(fattr->cf_mode & S_IFREG)) | ||
297 | /* it's not a symlink */ | ||
298 | return false; | ||
299 | 241 | ||
300 | if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) | 242 | if (tcon->ses->server->ops->query_mf_symlink) |
301 | /* it's not a symlink */ | 243 | rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, |
302 | return false; | 244 | cifs_sb, path, buf, &bytes_read); |
303 | 245 | else | |
304 | return true; | 246 | rc = -ENOSYS; |
305 | } | ||
306 | |||
307 | int | ||
308 | open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, | ||
309 | unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, | ||
310 | unsigned int xid) | ||
311 | { | ||
312 | int rc; | ||
313 | int oplock = 0; | ||
314 | __u16 netfid = 0; | ||
315 | struct tcon_link *tlink; | ||
316 | struct cifs_tcon *ptcon; | ||
317 | struct cifs_io_parms io_parms; | ||
318 | int buf_type = CIFS_NO_BUFFER; | ||
319 | FILE_ALL_INFO file_info; | ||
320 | |||
321 | tlink = cifs_sb_tlink(cifs_sb); | ||
322 | if (IS_ERR(tlink)) | ||
323 | return PTR_ERR(tlink); | ||
324 | ptcon = tlink_tcon(tlink); | ||
325 | 247 | ||
326 | rc = CIFSSMBOpen(xid, ptcon, path, FILE_OPEN, GENERIC_READ, | 248 | if (rc) |
327 | CREATE_NOT_DIR, &netfid, &oplock, &file_info, | 249 | goto out; |
328 | cifs_sb->local_nls, | ||
329 | cifs_sb->mnt_cifs_flags & | ||
330 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
331 | if (rc != 0) { | ||
332 | cifs_put_tlink(tlink); | ||
333 | return rc; | ||
334 | } | ||
335 | 250 | ||
336 | if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { | 251 | if (bytes_read == 0) { /* not a symlink */ |
337 | CIFSSMBClose(xid, ptcon, netfid); | 252 | rc = -EINVAL; |
338 | cifs_put_tlink(tlink); | 253 | goto out; |
339 | /* it's not a symlink */ | ||
340 | return rc; | ||
341 | } | 254 | } |
342 | 255 | ||
343 | io_parms.netfid = netfid; | 256 | rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo); |
344 | io_parms.pid = current->tgid; | 257 | out: |
345 | io_parms.tcon = ptcon; | 258 | kfree(buf); |
346 | io_parms.offset = 0; | ||
347 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
348 | |||
349 | rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); | ||
350 | CIFSSMBClose(xid, ptcon, netfid); | ||
351 | cifs_put_tlink(tlink); | ||
352 | return rc; | 259 | return rc; |
353 | } | 260 | } |
354 | 261 | ||
355 | |||
356 | int | 262 | int |
357 | CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, | 263 | check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, |
358 | struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | 264 | struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
359 | const unsigned char *path) | 265 | const unsigned char *path) |
360 | { | 266 | { |
361 | int rc; | 267 | int rc; |
362 | u8 *buf = NULL; | 268 | u8 *buf = NULL; |
363 | unsigned int link_len = 0; | 269 | unsigned int link_len = 0; |
364 | unsigned int bytes_read = 0; | 270 | unsigned int bytes_read = 0; |
365 | 271 | ||
366 | if (!CIFSCouldBeMFSymlink(fattr)) | 272 | if (!couldbe_mf_symlink(fattr)) |
367 | /* it's not a symlink */ | 273 | /* it's not a symlink */ |
368 | return 0; | 274 | return 0; |
369 | 275 | ||
@@ -372,8 +278,8 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, | |||
372 | return -ENOMEM; | 278 | return -ENOMEM; |
373 | 279 | ||
374 | if (tcon->ses->server->ops->query_mf_symlink) | 280 | if (tcon->ses->server->ops->query_mf_symlink) |
375 | rc = tcon->ses->server->ops->query_mf_symlink(path, buf, | 281 | rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, |
376 | &bytes_read, cifs_sb, xid); | 282 | cifs_sb, path, buf, &bytes_read); |
377 | else | 283 | else |
378 | rc = -ENOSYS; | 284 | rc = -ENOSYS; |
379 | 285 | ||
@@ -383,7 +289,7 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, | |||
383 | if (bytes_read == 0) /* not a symlink */ | 289 | if (bytes_read == 0) /* not a symlink */ |
384 | goto out; | 290 | goto out; |
385 | 291 | ||
386 | rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); | 292 | rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL); |
387 | if (rc == -EINVAL) { | 293 | if (rc == -EINVAL) { |
388 | /* it's not a symlink */ | 294 | /* it's not a symlink */ |
389 | rc = 0; | 295 | rc = 0; |
@@ -403,6 +309,95 @@ out: | |||
403 | return rc; | 309 | return rc; |
404 | } | 310 | } |
405 | 311 | ||
312 | /* | ||
313 | * SMB 1.0 Protocol specific functions | ||
314 | */ | ||
315 | |||
316 | int | ||
317 | cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||
318 | struct cifs_sb_info *cifs_sb, const unsigned char *path, | ||
319 | char *pbuf, unsigned int *pbytes_read) | ||
320 | { | ||
321 | int rc; | ||
322 | int oplock = 0; | ||
323 | struct cifs_fid fid; | ||
324 | struct cifs_open_parms oparms; | ||
325 | struct cifs_io_parms io_parms; | ||
326 | int buf_type = CIFS_NO_BUFFER; | ||
327 | FILE_ALL_INFO file_info; | ||
328 | |||
329 | oparms.tcon = tcon; | ||
330 | oparms.cifs_sb = cifs_sb; | ||
331 | oparms.desired_access = GENERIC_READ; | ||
332 | oparms.create_options = CREATE_NOT_DIR; | ||
333 | oparms.disposition = FILE_OPEN; | ||
334 | oparms.path = path; | ||
335 | oparms.fid = &fid; | ||
336 | oparms.reconnect = false; | ||
337 | |||
338 | rc = CIFS_open(xid, &oparms, &oplock, &file_info); | ||
339 | if (rc) | ||
340 | return rc; | ||
341 | |||
342 | if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) | ||
343 | /* it's not a symlink */ | ||
344 | goto out; | ||
345 | |||
346 | io_parms.netfid = fid.netfid; | ||
347 | io_parms.pid = current->tgid; | ||
348 | io_parms.tcon = tcon; | ||
349 | io_parms.offset = 0; | ||
350 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
351 | |||
352 | rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); | ||
353 | out: | ||
354 | CIFSSMBClose(xid, tcon, fid.netfid); | ||
355 | return rc; | ||
356 | } | ||
357 | |||
358 | int | ||
359 | cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||
360 | struct cifs_sb_info *cifs_sb, const unsigned char *path, | ||
361 | char *pbuf, unsigned int *pbytes_written) | ||
362 | { | ||
363 | int rc; | ||
364 | int oplock = 0; | ||
365 | struct cifs_fid fid; | ||
366 | struct cifs_open_parms oparms; | ||
367 | struct cifs_io_parms io_parms; | ||
368 | int create_options = CREATE_NOT_DIR; | ||
369 | |||
370 | if (backup_cred(cifs_sb)) | ||
371 | create_options |= CREATE_OPEN_BACKUP_INTENT; | ||
372 | |||
373 | oparms.tcon = tcon; | ||
374 | oparms.cifs_sb = cifs_sb; | ||
375 | oparms.desired_access = GENERIC_WRITE; | ||
376 | oparms.create_options = create_options; | ||
377 | oparms.disposition = FILE_OPEN; | ||
378 | oparms.path = path; | ||
379 | oparms.fid = &fid; | ||
380 | oparms.reconnect = false; | ||
381 | |||
382 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
383 | if (rc) | ||
384 | return rc; | ||
385 | |||
386 | io_parms.netfid = fid.netfid; | ||
387 | io_parms.pid = current->tgid; | ||
388 | io_parms.tcon = tcon; | ||
389 | io_parms.offset = 0; | ||
390 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
391 | |||
392 | rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0); | ||
393 | CIFSSMBClose(xid, tcon, fid.netfid); | ||
394 | return rc; | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | * M-F Symlink Functions - End | ||
399 | */ | ||
400 | |||
406 | int | 401 | int |
407 | cifs_hardlink(struct dentry *old_file, struct inode *inode, | 402 | cifs_hardlink(struct dentry *old_file, struct inode *inode, |
408 | struct dentry *direntry) | 403 | struct dentry *direntry) |
@@ -438,8 +433,10 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, | |||
438 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 433 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
439 | else { | 434 | else { |
440 | server = tcon->ses->server; | 435 | server = tcon->ses->server; |
441 | if (!server->ops->create_hardlink) | 436 | if (!server->ops->create_hardlink) { |
442 | return -ENOSYS; | 437 | rc = -ENOSYS; |
438 | goto cifs_hl_exit; | ||
439 | } | ||
443 | rc = server->ops->create_hardlink(xid, tcon, from_name, to_name, | 440 | rc = server->ops->create_hardlink(xid, tcon, from_name, to_name, |
444 | cifs_sb); | 441 | cifs_sb); |
445 | if ((rc == -EIO) || (rc == -EINVAL)) | 442 | if ((rc == -EIO) || (rc == -EINVAL)) |
@@ -530,15 +527,10 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) | |||
530 | * and fallback to UNIX Extensions Symlinks. | 527 | * and fallback to UNIX Extensions Symlinks. |
531 | */ | 528 | */ |
532 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) | 529 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) |
533 | rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path, | 530 | rc = query_mf_symlink(xid, tcon, cifs_sb, full_path, |
534 | cifs_sb->local_nls, | 531 | &target_path); |
535 | cifs_sb->mnt_cifs_flags & | ||
536 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
537 | 532 | ||
538 | if ((rc != 0) && cap_unix(tcon->ses)) | 533 | if (rc != 0 && server->ops->query_symlink) |
539 | rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, | ||
540 | cifs_sb->local_nls); | ||
541 | else if (rc != 0 && server->ops->query_symlink) | ||
542 | rc = server->ops->query_symlink(xid, tcon, full_path, | 534 | rc = server->ops->query_symlink(xid, tcon, full_path, |
543 | &target_path, cifs_sb); | 535 | &target_path, cifs_sb); |
544 | 536 | ||
@@ -587,8 +579,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) | |||
587 | 579 | ||
588 | /* BB what if DFS and this volume is on different share? BB */ | 580 | /* BB what if DFS and this volume is on different share? BB */ |
589 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) | 581 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) |
590 | rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, | 582 | rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname); |
591 | cifs_sb); | ||
592 | else if (pTcon->unix_ext) | 583 | else if (pTcon->unix_ext) |
593 | rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, | 584 | rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, |
594 | cifs_sb->local_nls); | 585 | cifs_sb->local_nls); |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 5940ecabbe6a..b15862e0f68c 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -749,7 +749,7 @@ static int cifs_filldir(char *find_entry, struct file *file, | |||
749 | } | 749 | } |
750 | 750 | ||
751 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && | 751 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && |
752 | CIFSCouldBeMFSymlink(&fattr)) | 752 | couldbe_mf_symlink(&fattr)) |
753 | /* | 753 | /* |
754 | * trying to get the type and mode can be slow, | 754 | * trying to get the type and mode can be slow, |
755 | * so just call those regular files for now, and mark | 755 | * so just call those regular files for now, and mark |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 5f5ba0dc2ee1..9ac5bfc9cc56 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
@@ -560,17 +560,24 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
560 | if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) { | 560 | if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) { |
561 | int tmprc; | 561 | int tmprc; |
562 | int oplock = 0; | 562 | int oplock = 0; |
563 | __u16 netfid; | 563 | struct cifs_fid fid; |
564 | struct cifs_open_parms oparms; | ||
565 | |||
566 | oparms.tcon = tcon; | ||
567 | oparms.cifs_sb = cifs_sb; | ||
568 | oparms.desired_access = FILE_READ_ATTRIBUTES; | ||
569 | oparms.create_options = 0; | ||
570 | oparms.disposition = FILE_OPEN; | ||
571 | oparms.path = full_path; | ||
572 | oparms.fid = &fid; | ||
573 | oparms.reconnect = false; | ||
564 | 574 | ||
565 | /* Need to check if this is a symbolic link or not */ | 575 | /* Need to check if this is a symbolic link or not */ |
566 | tmprc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 576 | tmprc = CIFS_open(xid, &oparms, &oplock, NULL); |
567 | FILE_READ_ATTRIBUTES, 0, &netfid, &oplock, | ||
568 | NULL, cifs_sb->local_nls, | ||
569 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
570 | if (tmprc == -EOPNOTSUPP) | 577 | if (tmprc == -EOPNOTSUPP) |
571 | *symlink = true; | 578 | *symlink = true; |
572 | else | 579 | else |
573 | CIFSSMBClose(xid, tcon, netfid); | 580 | CIFSSMBClose(xid, tcon, fid.netfid); |
574 | } | 581 | } |
575 | 582 | ||
576 | return rc; | 583 | return rc; |
@@ -705,12 +712,7 @@ cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, | |||
705 | oparms->cifs_sb->local_nls, | 712 | oparms->cifs_sb->local_nls, |
706 | oparms->cifs_sb->mnt_cifs_flags | 713 | oparms->cifs_sb->mnt_cifs_flags |
707 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | 714 | & CIFS_MOUNT_MAP_SPECIAL_CHR); |
708 | return CIFSSMBOpen(xid, oparms->tcon, oparms->path, | 715 | return CIFS_open(xid, oparms, oplock, buf); |
709 | oparms->disposition, oparms->desired_access, | ||
710 | oparms->create_options, &oparms->fid->netfid, oplock, | ||
711 | buf, oparms->cifs_sb->local_nls, | ||
712 | oparms->cifs_sb->mnt_cifs_flags & | ||
713 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
714 | } | 716 | } |
715 | 717 | ||
716 | static void | 718 | static void |
@@ -761,8 +763,9 @@ smb_set_file_info(struct inode *inode, const char *full_path, | |||
761 | { | 763 | { |
762 | int oplock = 0; | 764 | int oplock = 0; |
763 | int rc; | 765 | int rc; |
764 | __u16 netfid; | ||
765 | __u32 netpid; | 766 | __u32 netpid; |
767 | struct cifs_fid fid; | ||
768 | struct cifs_open_parms oparms; | ||
766 | struct cifsFileInfo *open_file; | 769 | struct cifsFileInfo *open_file; |
767 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 770 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
768 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 771 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
@@ -772,7 +775,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, | |||
772 | /* if the file is already open for write, just use that fileid */ | 775 | /* if the file is already open for write, just use that fileid */ |
773 | open_file = find_writable_file(cinode, true); | 776 | open_file = find_writable_file(cinode, true); |
774 | if (open_file) { | 777 | if (open_file) { |
775 | netfid = open_file->fid.netfid; | 778 | fid.netfid = open_file->fid.netfid; |
776 | netpid = open_file->pid; | 779 | netpid = open_file->pid; |
777 | tcon = tlink_tcon(open_file->tlink); | 780 | tcon = tlink_tcon(open_file->tlink); |
778 | goto set_via_filehandle; | 781 | goto set_via_filehandle; |
@@ -796,12 +799,17 @@ smb_set_file_info(struct inode *inode, const char *full_path, | |||
796 | goto out; | 799 | goto out; |
797 | } | 800 | } |
798 | 801 | ||
799 | cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); | 802 | oparms.tcon = tcon; |
800 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 803 | oparms.cifs_sb = cifs_sb; |
801 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, | 804 | oparms.desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES; |
802 | &netfid, &oplock, NULL, cifs_sb->local_nls, | 805 | oparms.create_options = CREATE_NOT_DIR; |
803 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 806 | oparms.disposition = FILE_OPEN; |
807 | oparms.path = full_path; | ||
808 | oparms.fid = &fid; | ||
809 | oparms.reconnect = false; | ||
804 | 810 | ||
811 | cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); | ||
812 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
805 | if (rc != 0) { | 813 | if (rc != 0) { |
806 | if (rc == -EIO) | 814 | if (rc == -EIO) |
807 | rc = -EINVAL; | 815 | rc = -EINVAL; |
@@ -811,12 +819,12 @@ smb_set_file_info(struct inode *inode, const char *full_path, | |||
811 | netpid = current->tgid; | 819 | netpid = current->tgid; |
812 | 820 | ||
813 | set_via_filehandle: | 821 | set_via_filehandle: |
814 | rc = CIFSSMBSetFileInfo(xid, tcon, buf, netfid, netpid); | 822 | rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid); |
815 | if (!rc) | 823 | if (!rc) |
816 | cinode->cifsAttrs = le32_to_cpu(buf->Attributes); | 824 | cinode->cifsAttrs = le32_to_cpu(buf->Attributes); |
817 | 825 | ||
818 | if (open_file == NULL) | 826 | if (open_file == NULL) |
819 | CIFSSMBClose(xid, tcon, netfid); | 827 | CIFSSMBClose(xid, tcon, fid.netfid); |
820 | else | 828 | else |
821 | cifsFileInfo_put(open_file); | 829 | cifsFileInfo_put(open_file); |
822 | out: | 830 | out: |
@@ -908,33 +916,80 @@ cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset, | |||
908 | } | 916 | } |
909 | 917 | ||
910 | static int | 918 | static int |
919 | cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon, | ||
920 | const unsigned char *searchName, char **symlinkinfo, | ||
921 | const struct nls_table *nls_codepage) | ||
922 | { | ||
923 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
924 | int rc; | ||
925 | unsigned int num_referrals = 0; | ||
926 | struct dfs_info3_param *referrals = NULL; | ||
927 | |||
928 | rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage, | ||
929 | &num_referrals, &referrals, 0); | ||
930 | |||
931 | if (!rc && num_referrals > 0) { | ||
932 | *symlinkinfo = kstrndup(referrals->node_name, | ||
933 | strlen(referrals->node_name), | ||
934 | GFP_KERNEL); | ||
935 | if (!*symlinkinfo) | ||
936 | rc = -ENOMEM; | ||
937 | free_dfs_info_array(referrals, num_referrals); | ||
938 | } | ||
939 | return rc; | ||
940 | #else /* No DFS support */ | ||
941 | return -EREMOTE; | ||
942 | #endif | ||
943 | } | ||
944 | |||
945 | static int | ||
911 | cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, | 946 | cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, |
912 | const char *full_path, char **target_path, | 947 | const char *full_path, char **target_path, |
913 | struct cifs_sb_info *cifs_sb) | 948 | struct cifs_sb_info *cifs_sb) |
914 | { | 949 | { |
915 | int rc; | 950 | int rc; |
916 | int oplock = 0; | 951 | int oplock = 0; |
917 | __u16 netfid; | 952 | struct cifs_fid fid; |
953 | struct cifs_open_parms oparms; | ||
918 | 954 | ||
919 | cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); | 955 | cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); |
920 | 956 | ||
921 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 957 | /* Check for unix extensions */ |
922 | FILE_READ_ATTRIBUTES, OPEN_REPARSE_POINT, &netfid, | 958 | if (cap_unix(tcon->ses)) { |
923 | &oplock, NULL, cifs_sb->local_nls, | 959 | rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, |
924 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 960 | cifs_sb->local_nls); |
961 | if (rc == -EREMOTE) | ||
962 | rc = cifs_unix_dfs_readlink(xid, tcon, full_path, | ||
963 | target_path, | ||
964 | cifs_sb->local_nls); | ||
965 | |||
966 | goto out; | ||
967 | } | ||
968 | |||
969 | oparms.tcon = tcon; | ||
970 | oparms.cifs_sb = cifs_sb; | ||
971 | oparms.desired_access = FILE_READ_ATTRIBUTES; | ||
972 | oparms.create_options = OPEN_REPARSE_POINT; | ||
973 | oparms.disposition = FILE_OPEN; | ||
974 | oparms.path = full_path; | ||
975 | oparms.fid = &fid; | ||
976 | oparms.reconnect = false; | ||
977 | |||
978 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
925 | if (rc) | 979 | if (rc) |
926 | return rc; | 980 | goto out; |
927 | 981 | ||
928 | rc = CIFSSMBQuerySymLink(xid, tcon, netfid, target_path, | 982 | rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path, |
929 | cifs_sb->local_nls); | 983 | cifs_sb->local_nls); |
930 | if (rc) { | 984 | if (rc) |
931 | CIFSSMBClose(xid, tcon, netfid); | 985 | goto out_close; |
932 | return rc; | ||
933 | } | ||
934 | 986 | ||
935 | convert_delimiter(*target_path, '/'); | 987 | convert_delimiter(*target_path, '/'); |
936 | CIFSSMBClose(xid, tcon, netfid); | 988 | out_close: |
937 | cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); | 989 | CIFSSMBClose(xid, tcon, fid.netfid); |
990 | out: | ||
991 | if (!rc) | ||
992 | cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); | ||
938 | return rc; | 993 | return rc; |
939 | } | 994 | } |
940 | 995 | ||
@@ -1009,7 +1064,8 @@ struct smb_version_operations smb1_operations = { | |||
1009 | .mand_lock = cifs_mand_lock, | 1064 | .mand_lock = cifs_mand_lock, |
1010 | .mand_unlock_range = cifs_unlock_range, | 1065 | .mand_unlock_range = cifs_unlock_range, |
1011 | .push_mand_locks = cifs_push_mandatory_locks, | 1066 | .push_mand_locks = cifs_push_mandatory_locks, |
1012 | .query_mf_symlink = open_query_close_cifs_symlink, | 1067 | .query_mf_symlink = cifs_query_mf_symlink, |
1068 | .create_mf_symlink = cifs_create_mf_symlink, | ||
1013 | .is_read_op = cifs_is_read_op, | 1069 | .is_read_op = cifs_is_read_op, |
1014 | }; | 1070 | }; |
1015 | 1071 | ||
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 09afda4cc58e..95c43bb20335 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -82,9 +82,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) | |||
82 | goto remove_ea_exit; | 82 | goto remove_ea_exit; |
83 | 83 | ||
84 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ | 84 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ |
85 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL, | 85 | if (pTcon->ses->server->ops->set_EA) |
86 | (__u16)0, cifs_sb->local_nls, | 86 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, |
87 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 87 | full_path, ea_name, NULL, (__u16)0, |
88 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
89 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
88 | } | 90 | } |
89 | remove_ea_exit: | 91 | remove_ea_exit: |
90 | kfree(full_path); | 92 | kfree(full_path); |
@@ -149,18 +151,22 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
149 | cifs_dbg(FYI, "attempt to set cifs inode metadata\n"); | 151 | cifs_dbg(FYI, "attempt to set cifs inode metadata\n"); |
150 | 152 | ||
151 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ | 153 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ |
152 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, | 154 | if (pTcon->ses->server->ops->set_EA) |
153 | (__u16)value_size, cifs_sb->local_nls, | 155 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, |
154 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 156 | full_path, ea_name, ea_value, (__u16)value_size, |
157 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
158 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
155 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) | 159 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) |
156 | == 0) { | 160 | == 0) { |
157 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | 161 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) |
158 | goto set_ea_exit; | 162 | goto set_ea_exit; |
159 | 163 | ||
160 | ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ | 164 | ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ |
161 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, | 165 | if (pTcon->ses->server->ops->set_EA) |
162 | (__u16)value_size, cifs_sb->local_nls, | 166 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, |
163 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 167 | full_path, ea_name, ea_value, (__u16)value_size, |
168 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
169 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
164 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | 170 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, |
165 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | 171 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { |
166 | #ifdef CONFIG_CIFS_ACL | 172 | #ifdef CONFIG_CIFS_ACL |
@@ -272,17 +278,21 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
272 | /* revalidate/getattr then populate from inode */ | 278 | /* revalidate/getattr then populate from inode */ |
273 | } /* BB add else when above is implemented */ | 279 | } /* BB add else when above is implemented */ |
274 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ | 280 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ |
275 | rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, | 281 | if (pTcon->ses->server->ops->query_all_EAs) |
276 | buf_size, cifs_sb->local_nls, | 282 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, |
277 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 283 | full_path, ea_name, ea_value, buf_size, |
284 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
285 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
278 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { | 286 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { |
279 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | 287 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) |
280 | goto get_ea_exit; | 288 | goto get_ea_exit; |
281 | 289 | ||
282 | ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ | 290 | ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ |
283 | rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, | 291 | if (pTcon->ses->server->ops->query_all_EAs) |
284 | buf_size, cifs_sb->local_nls, | 292 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, |
285 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 293 | full_path, ea_name, ea_value, buf_size, |
294 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
295 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
286 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, | 296 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, |
287 | strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { | 297 | strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { |
288 | #ifdef CONFIG_CIFS_POSIX | 298 | #ifdef CONFIG_CIFS_POSIX |
@@ -400,11 +410,12 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
400 | /* if proc/fs/cifs/streamstoxattr is set then | 410 | /* if proc/fs/cifs/streamstoxattr is set then |
401 | search server for EAs or streams to | 411 | search server for EAs or streams to |
402 | returns as xattrs */ | 412 | returns as xattrs */ |
403 | rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data, | ||
404 | buf_size, cifs_sb->local_nls, | ||
405 | cifs_sb->mnt_cifs_flags & | ||
406 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
407 | 413 | ||
414 | if (pTcon->ses->server->ops->query_all_EAs) | ||
415 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, | ||
416 | full_path, NULL, data, buf_size, | ||
417 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
418 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
408 | list_ea_exit: | 419 | list_ea_exit: |
409 | kfree(full_path); | 420 | kfree(full_path); |
410 | free_xid(xid); | 421 | free_xid(xid); |