]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 1 Feb 2014 18:52:45 +0000 (10:52 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 1 Feb 2014 18:52:45 +0000 (10:52 -0800)
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()

fs/cifs/cifsacl.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/link.c
fs/cifs/readdir.c
fs/cifs/smb1ops.c
fs/cifs/xattr.c

index 51f5e0ee7237210c78166db95cec9b26c1611ed5..8f9b4f710d4a31ea651f64586fa2469edd92c2fa 100644 (file)
@@ -895,9 +895,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
        int oplock = 0;
        unsigned int xid;
        int rc, create_options = 0;
-       __u16 fid;
        struct cifs_tcon *tcon;
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+       struct cifs_fid fid;
+       struct cifs_open_parms oparms;
 
        if (IS_ERR(tlink))
                return ERR_CAST(tlink);
@@ -908,12 +909,19 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
        if (backup_cred(cifs_sb))
                create_options |= CREATE_OPEN_BACKUP_INTENT;
 
-       rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
-                       create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
-                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
+       oparms.desired_access = READ_CONTROL;
+       oparms.create_options = create_options;
+       oparms.disposition = FILE_OPEN;
+       oparms.path = path;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
+
+       rc = CIFS_open(xid, &oparms, &oplock, NULL);
        if (!rc) {
-               rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
-               CIFSSMBClose(xid, tcon, fid);
+               rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
+               CIFSSMBClose(xid, tcon, fid.netfid);
        }
 
        cifs_put_tlink(tlink);
@@ -950,10 +958,11 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
        int oplock = 0;
        unsigned int xid;
        int rc, access_flags, create_options = 0;
-       __u16 fid;
        struct cifs_tcon *tcon;
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+       struct cifs_fid fid;
+       struct cifs_open_parms oparms;
 
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
@@ -969,18 +978,25 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
        else
                access_flags = WRITE_DAC;
 
-       rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
-                       create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
-                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
+       oparms.desired_access = access_flags;
+       oparms.create_options = create_options;
+       oparms.disposition = FILE_OPEN;
+       oparms.path = path;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
+
+       rc = CIFS_open(xid, &oparms, &oplock, NULL);
        if (rc) {
                cifs_dbg(VFS, "Unable to open file to set ACL\n");
                goto out;
        }
 
-       rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
+       rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
        cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
 
-       CIFSSMBClose(xid, tcon, fid);
+       CIFSSMBClose(xid, tcon, fid.netfid);
 out:
        free_xid(xid);
        cifs_put_tlink(tlink);
index f918a998a08758caac54bf8205cd7da7705c1efc..a245d1809ed8d63dc7ee5cbc5320bb117a12c71e 100644 (file)
@@ -370,8 +370,12 @@ struct smb_version_operations {
        void (*new_lease_key)(struct cifs_fid *);
        int (*generate_signingkey)(struct cifs_ses *);
        int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
-       int (*query_mf_symlink)(const unsigned char *, char *, unsigned int *,
-                               struct cifs_sb_info *, unsigned int);
+       int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
+                               struct cifs_sb_info *, const unsigned char *,
+                               char *, unsigned int *);
+       int (*create_mf_symlink)(unsigned int, struct cifs_tcon *,
+                                struct cifs_sb_info *, const unsigned char *,
+                                char *, unsigned int *);
        /* if we can do cache read operations */
        bool (*is_read_op)(__u32);
        /* set oplock level for the inode */
@@ -385,6 +389,12 @@ struct smb_version_operations {
                        struct cifsFileInfo *target_file, u64 src_off, u64 len,
                        u64 dest_off);
        int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
+       ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *,
+                       const unsigned char *, const unsigned char *, char *,
+                       size_t, const struct nls_table *, int);
+       int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
+                       const char *, const void *, const __u16,
+                       const struct nls_table *, int);
 };
 
 struct smb_version_values {
index 2c29db6a247e4788256461100bed11ac79648d26..79e6e9a93a8ce984420ef8dc68fa3d941ff1f045 100644 (file)
@@ -362,11 +362,8 @@ extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
                               const struct nls_table *nls_codepage);
 extern int CIFSSMB_set_compression(const unsigned int xid,
                                   struct cifs_tcon *tcon, __u16 fid);
-extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
-                       const char *fileName, const int disposition,
-                       const int access_flags, const int omode,
-                       __u16 *netfid, int *pOplock, FILE_ALL_INFO *,
-                       const struct nls_table *nls_codepage, int remap);
+extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms,
+                    int *oplock, FILE_ALL_INFO *buf);
 extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
                        const char *fileName, const int disposition,
                        const int access_flags, const int omode,
@@ -476,8 +473,8 @@ extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
 extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
                        const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
 extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
-extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr);
-extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+extern bool couldbe_mf_symlink(const struct cifs_fattr *fattr);
+extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
                              struct cifs_sb_info *cifs_sb,
                              struct cifs_fattr *fattr,
                              const unsigned char *path);
@@ -496,7 +493,12 @@ void cifs_writev_complete(struct work_struct *work);
 struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
                                                work_func_t complete);
 void cifs_writedata_release(struct kref *refcount);
-int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
-                       unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
-                       unsigned int xid);
+int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+                         struct cifs_sb_info *cifs_sb,
+                         const unsigned char *path, char *pbuf,
+                         unsigned int *pbytes_read);
+int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+                          struct cifs_sb_info *cifs_sb,
+                          const unsigned char *path, char *pbuf,
+                          unsigned int *pbytes_written);
 #endif                 /* _CIFSPROTO_H */
index d707edb6b852695f0de3993c9ef9cd12a3f909f3..4d881c35eecaa035717b52d9c19b9dac00dd9dae 100644 (file)
@@ -1273,104 +1273,124 @@ OldOpenRetry:
 }
 
 int
-CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
-           const char *fileName, const int openDisposition,
-           const int access_flags, const int create_options, __u16 *netfid,
-           int *pOplock, FILE_ALL_INFO *pfile_info,
-           const struct nls_table *nls_codepage, int remap)
+CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
+         FILE_ALL_INFO *buf)
 {
        int rc = -EACCES;
-       OPEN_REQ *pSMB = NULL;
-       OPEN_RSP *pSMBr = NULL;
+       OPEN_REQ *req = NULL;
+       OPEN_RSP *rsp = NULL;
        int bytes_returned;
        int name_len;
        __u16 count;
+       struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
+       struct cifs_tcon *tcon = oparms->tcon;
+       int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
+       const struct nls_table *nls = cifs_sb->local_nls;
+       int create_options = oparms->create_options;
+       int desired_access = oparms->desired_access;
+       int disposition = oparms->disposition;
+       const char *path = oparms->path;
 
 openRetry:
-       rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
+                     (void **)&rsp);
        if (rc)
                return rc;
 
-       pSMB->AndXCommand = 0xFF;       /* none */
+       /* no commands go after this */
+       req->AndXCommand = 0xFF;
 
-       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               count = 1;      /* account for one byte pad to word boundary */
-               name_len =
-                   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
-                                      fileName, PATH_MAX, nls_codepage, remap);
-               name_len++;     /* trailing null */
+       if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
+               /* account for one byte pad to word boundary */
+               count = 1;
+               name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
+                                             path, PATH_MAX, nls, remap);
+               /* trailing null */
+               name_len++;
                name_len *= 2;
-               pSMB->NameLength = cpu_to_le16(name_len);
-       } else {                /* BB improve check for buffer overruns BB */
-               count = 0;      /* no pad */
-               name_len = strnlen(fileName, PATH_MAX);
-               name_len++;     /* trailing null */
-               pSMB->NameLength = cpu_to_le16(name_len);
-               strncpy(pSMB->fileName, fileName, name_len);
+               req->NameLength = cpu_to_le16(name_len);
+       } else {
+               /* BB improve check for buffer overruns BB */
+               /* no pad */
+               count = 0;
+               name_len = strnlen(path, PATH_MAX);
+               /* trailing null */
+               name_len++;
+               req->NameLength = cpu_to_le16(name_len);
+               strncpy(req->fileName, path, name_len);
        }
-       if (*pOplock & REQ_OPLOCK)
-               pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
-       else if (*pOplock & REQ_BATCHOPLOCK)
-               pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
-       pSMB->DesiredAccess = cpu_to_le32(access_flags);
-       pSMB->AllocationSize = 0;
-       /* set file as system file if special file such
-          as fifo and server expecting SFU style and
-          no Unix extensions */
+
+       if (*oplock & REQ_OPLOCK)
+               req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
+       else if (*oplock & REQ_BATCHOPLOCK)
+               req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
+
+       req->DesiredAccess = cpu_to_le32(desired_access);
+       req->AllocationSize = 0;
+
+       /*
+        * Set file as system file if special file such as fifo and server
+        * expecting SFU style and no Unix extensions.
+        */
        if (create_options & CREATE_OPTION_SPECIAL)
-               pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
+               req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
        else
-               pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
+               req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
 
-       /* XP does not handle ATTR_POSIX_SEMANTICS */
-       /* but it helps speed up case sensitive checks for other
-       servers such as Samba */
+       /*
+        * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
+        * sensitive checks for other servers such as Samba.
+        */
        if (tcon->ses->capabilities & CAP_UNIX)
-               pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
+               req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
 
        if (create_options & CREATE_OPTION_READONLY)
-               pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
+               req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
+
+       req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
+       req->CreateDisposition = cpu_to_le32(disposition);
+       req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
 
-       pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
-       pSMB->CreateDisposition = cpu_to_le32(openDisposition);
-       pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
        /* BB Expirement with various impersonation levels and verify */
-       pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
-       pSMB->SecurityFlags =
-           SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
+       req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
+       req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
 
        count += name_len;
-       inc_rfc1001_len(pSMB, count);
+       inc_rfc1001_len(req, count);
 
-       pSMB->ByteCount = cpu_to_le16(count);
-       /* long_op set to 1 to allow for oplock break timeouts */
-       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-                       (struct smb_hdr *)pSMBr, &bytes_returned, 0);
+       req->ByteCount = cpu_to_le16(count);
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
+                        (struct smb_hdr *)rsp, &bytes_returned, 0);
        cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
        if (rc) {
                cifs_dbg(FYI, "Error in Open = %d\n", rc);
-       } else {
-               *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
-               *netfid = pSMBr->Fid;   /* cifs fid stays in le */
-               /* Let caller know file was created so we can set the mode. */
-               /* Do we care about the CreateAction in any other cases? */
-               if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
-                       *pOplock |= CIFS_CREATE_ACTION;
-               if (pfile_info) {
-                       memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
-                               36 /* CreationTime to Attributes */);
-                       /* the file_info buf is endian converted by caller */
-                       pfile_info->AllocationSize = pSMBr->AllocationSize;
-                       pfile_info->EndOfFile = pSMBr->EndOfFile;
-                       pfile_info->NumberOfLinks = cpu_to_le32(1);
-                       pfile_info->DeletePending = 0;
-               }
+               cifs_buf_release(req);
+               if (rc == -EAGAIN)
+                       goto openRetry;
+               return rc;
        }
 
-       cifs_buf_release(pSMB);
-       if (rc == -EAGAIN)
-               goto openRetry;
+       /* 1 byte no need to le_to_cpu */
+       *oplock = rsp->OplockLevel;
+       /* cifs fid stays in le */
+       oparms->fid->netfid = rsp->Fid;
+
+       /* Let caller know file was created so we can set the mode. */
+       /* Do we care about the CreateAction in any other cases? */
+       if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
+               *oplock |= CIFS_CREATE_ACTION;
+
+       if (buf) {
+               /* copy from CreationTime to Attributes */
+               memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
+               /* the file_info buf is endian converted by caller */
+               buf->AllocationSize = rsp->AllocationSize;
+               buf->EndOfFile = rsp->EndOfFile;
+               buf->NumberOfLinks = cpu_to_le32(1);
+               buf->DeletePending = 0;
+       }
+
+       cifs_buf_release(req);
        return rc;
 }
 
index a514e0a65f69b5936fbd60934b33938666f70dd0..d3a6796caa5a3fce527584ae6437b2a446663da4 100644 (file)
@@ -565,12 +565,13 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
        int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL;
        struct cifs_sb_info *cifs_sb;
        struct tcon_link *tlink;
-       struct cifs_tcon *pTcon;
+       struct cifs_tcon *tcon;
        struct cifs_io_parms io_parms;
        char *full_path = NULL;
        struct inode *newinode = NULL;
        int oplock = 0;
-       u16 fileHandle;
+       struct cifs_fid fid;
+       struct cifs_open_parms oparms;
        FILE_ALL_INFO *buf = NULL;
        unsigned int bytes_written;
        struct win_dev *pdev;
@@ -583,7 +584,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
 
-       pTcon = tlink_tcon(tlink);
+       tcon = tlink_tcon(tlink);
 
        xid = get_xid();
 
@@ -593,7 +594,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
                goto mknod_out;
        }
 
-       if (pTcon->unix_ext) {
+       if (tcon->unix_ext) {
                struct cifs_unix_set_info_args args = {
                        .mode   = mode & ~current_umask(),
                        .ctime  = NO_CHANGE_64,
@@ -608,7 +609,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
                        args.uid = INVALID_UID; /* no change */
                        args.gid = INVALID_GID; /* no change */
                }
-               rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
+               rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
                                            cifs_sb->local_nls,
                                            cifs_sb->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -640,42 +641,44 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
        if (backup_cred(cifs_sb))
                create_options |= CREATE_OPEN_BACKUP_INTENT;
 
-       rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
-                        GENERIC_WRITE, create_options,
-                        &fileHandle, &oplock, buf, cifs_sb->local_nls,
-                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
+       oparms.desired_access = GENERIC_WRITE;
+       oparms.create_options = create_options;
+       oparms.disposition = FILE_CREATE;
+       oparms.path = full_path;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
+
+       rc = CIFS_open(xid, &oparms, &oplock, buf);
        if (rc)
                goto mknod_out;
 
-       /* BB Do not bother to decode buf since no local inode yet to put
-        * timestamps in, but we can reuse it safely */
+       /*
+        * BB Do not bother to decode buf since no local inode yet to put
+        * timestamps in, but we can reuse it safely.
+        */
 
        pdev = (struct win_dev *)buf;
-       io_parms.netfid = fileHandle;
+       io_parms.netfid = fid.netfid;
        io_parms.pid = current->tgid;
-       io_parms.tcon = pTcon;
+       io_parms.tcon = tcon;
        io_parms.offset = 0;
        io_parms.length = sizeof(struct win_dev);
        if (S_ISCHR(mode)) {
                memcpy(pdev->type, "IntxCHR", 8);
-               pdev->major =
-                     cpu_to_le64(MAJOR(device_number));
-               pdev->minor =
-                     cpu_to_le64(MINOR(device_number));
-               rc = CIFSSMBWrite(xid, &io_parms,
-                       &bytes_written, (char *)pdev,
-                       NULL, 0);
+               pdev->major = cpu_to_le64(MAJOR(device_number));
+               pdev->minor = cpu_to_le64(MINOR(device_number));
+               rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev,
+                                 NULL, 0);
        } else if (S_ISBLK(mode)) {
                memcpy(pdev->type, "IntxBLK", 8);
-               pdev->major =
-                     cpu_to_le64(MAJOR(device_number));
-               pdev->minor =
-                     cpu_to_le64(MINOR(device_number));
-               rc = CIFSSMBWrite(xid, &io_parms,
-                       &bytes_written, (char *)pdev,
-                       NULL, 0);
+               pdev->major = cpu_to_le64(MAJOR(device_number));
+               pdev->minor = cpu_to_le64(MINOR(device_number));
+               rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev,
+                                 NULL, 0);
        } /* else if (S_ISFIFO) */
-       CIFSSMBClose(xid, pTcon, fileHandle);
+       CIFSSMBClose(xid, tcon, fid.netfid);
        d_drop(direntry);
 
        /* FIXME: add code here to set EAs */
index 5a5a87240fe2cfa971a17f7b673d06f9b2326e5f..853d6d1cc822280a0deb1e5106aff7d84323e869 100644 (file)
@@ -678,7 +678,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
 
        /*
         * Can not refresh inode by passing in file_info buf to be returned by
-        * CIFSSMBOpen and then calling get_inode_info with returned buf since
+        * ops->open and then calling get_inode_info with returned buf since
         * file might have write behind data that needs to be flushed and server
         * version of file size can be stale. If we knew for sure that inode was
         * not dirty locally we could do this.
index 49719b8228e58bd44b373fd4b39d844be9e2043b..9cb9679d735719b42f83b89e39b9c0bbd56fdd65 100644 (file)
@@ -383,10 +383,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
-                                              full_path);
+               int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
+                                            full_path);
                if (tmprc)
-                       cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
+                       cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
        }
 
        if (*pinode == NULL) {
@@ -404,18 +404,20 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 }
 
 static int
-cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
+cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
              struct cifs_sb_info *cifs_sb, unsigned int xid)
 {
        int rc;
        int oplock = 0;
-       __u16 netfid;
        struct tcon_link *tlink;
        struct cifs_tcon *tcon;
+       struct cifs_fid fid;
+       struct cifs_open_parms oparms;
        struct cifs_io_parms io_parms;
        char buf[24];
        unsigned int bytes_read;
        char *pbuf;
+       int buf_type = CIFS_NO_BUFFER;
 
        pbuf = buf;
 
@@ -436,62 +438,69 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
                return PTR_ERR(tlink);
        tcon = tlink_tcon(tlink);
 
-       rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
-                        CREATE_NOT_DIR, &netfid, &oplock, NULL,
-                        cifs_sb->local_nls,
-                        cifs_sb->mnt_cifs_flags &
-                               CIFS_MOUNT_MAP_SPECIAL_CHR);
-       if (rc == 0) {
-               int buf_type = CIFS_NO_BUFFER;
-                       /* Read header */
-               io_parms.netfid = netfid;
-               io_parms.pid = current->tgid;
-               io_parms.tcon = tcon;
-               io_parms.offset = 0;
-               io_parms.length = 24;
-               rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
-                                &buf_type);
-               if ((rc == 0) && (bytes_read >= 8)) {
-                       if (memcmp("IntxBLK", pbuf, 8) == 0) {
-                               cifs_dbg(FYI, "Block device\n");
-                               fattr->cf_mode |= S_IFBLK;
-                               fattr->cf_dtype = DT_BLK;
-                               if (bytes_read == 24) {
-                                       /* we have enough to decode dev num */
-                                       __u64 mjr; /* major */
-                                       __u64 mnr; /* minor */
-                                       mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
-                                       mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
-                                       fattr->cf_rdev = MKDEV(mjr, mnr);
-                               }
-                       } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
-                               cifs_dbg(FYI, "Char device\n");
-                               fattr->cf_mode |= S_IFCHR;
-                               fattr->cf_dtype = DT_CHR;
-                               if (bytes_read == 24) {
-                                       /* we have enough to decode dev num */
-                                       __u64 mjr; /* major */
-                                       __u64 mnr; /* minor */
-                                       mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
-                                       mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
-                                       fattr->cf_rdev = MKDEV(mjr, mnr);
-                               }
-                       } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
-                               cifs_dbg(FYI, "Symlink\n");
-                               fattr->cf_mode |= S_IFLNK;
-                               fattr->cf_dtype = DT_LNK;
-                       } else {
-                               fattr->cf_mode |= S_IFREG; /* file? */
-                               fattr->cf_dtype = DT_REG;
-                               rc = -EOPNOTSUPP;
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
+       oparms.desired_access = GENERIC_READ;
+       oparms.create_options = CREATE_NOT_DIR;
+       oparms.disposition = FILE_OPEN;
+       oparms.path = path;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
+
+       rc = CIFS_open(xid, &oparms, &oplock, NULL);
+       if (rc) {
+               cifs_put_tlink(tlink);
+               return rc;
+       }
+
+       /* Read header */
+       io_parms.netfid = fid.netfid;
+       io_parms.pid = current->tgid;
+       io_parms.tcon = tcon;
+       io_parms.offset = 0;
+       io_parms.length = 24;
+
+       rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
+       if ((rc == 0) && (bytes_read >= 8)) {
+               if (memcmp("IntxBLK", pbuf, 8) == 0) {
+                       cifs_dbg(FYI, "Block device\n");
+                       fattr->cf_mode |= S_IFBLK;
+                       fattr->cf_dtype = DT_BLK;
+                       if (bytes_read == 24) {
+                               /* we have enough to decode dev num */
+                               __u64 mjr; /* major */
+                               __u64 mnr; /* minor */
+                               mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
+                               mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
+                               fattr->cf_rdev = MKDEV(mjr, mnr);
                        }
+               } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
+                       cifs_dbg(FYI, "Char device\n");
+                       fattr->cf_mode |= S_IFCHR;
+                       fattr->cf_dtype = DT_CHR;
+                       if (bytes_read == 24) {
+                               /* we have enough to decode dev num */
+                               __u64 mjr; /* major */
+                               __u64 mnr; /* minor */
+                               mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
+                               mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
+                               fattr->cf_rdev = MKDEV(mjr, mnr);
+                       }
+               } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
+                       cifs_dbg(FYI, "Symlink\n");
+                       fattr->cf_mode |= S_IFLNK;
+                       fattr->cf_dtype = DT_LNK;
                } else {
-                       fattr->cf_mode |= S_IFREG; /* then it is a file */
+                       fattr->cf_mode |= S_IFREG; /* file? */
                        fattr->cf_dtype = DT_REG;
-                       rc = -EOPNOTSUPP; /* or some unknown SFU type */
+                       rc = -EOPNOTSUPP;
                }
-               CIFSSMBClose(xid, tcon, netfid);
+       } else {
+               fattr->cf_mode |= S_IFREG; /* then it is a file */
+               fattr->cf_dtype = DT_REG;
+               rc = -EOPNOTSUPP; /* or some unknown SFU type */
        }
+       CIFSSMBClose(xid, tcon, fid.netfid);
        cifs_put_tlink(tlink);
        return rc;
 }
@@ -800,10 +809,10 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
-                                          full_path);
+               tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
+                                        full_path);
                if (tmprc)
-                       cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
+                       cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
        }
 
        if (!*inode) {
@@ -1032,7 +1041,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
 {
        int oplock = 0;
        int rc;
-       __u16 netfid;
+       struct cifs_fid fid;
+       struct cifs_open_parms oparms;
        struct inode *inode = dentry->d_inode;
        struct cifsInodeInfo *cifsInode = CIFS_I(inode);
        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,
                goto out;
        }
 
-       rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
-                        DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
-                        &netfid, &oplock, NULL, cifs_sb->local_nls,
-                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
+       oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
+       oparms.create_options = CREATE_NOT_DIR;
+       oparms.disposition = FILE_OPEN;
+       oparms.path = full_path;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
+
+       rc = CIFS_open(xid, &oparms, &oplock, NULL);
        if (rc != 0)
                goto out;
 
@@ -1079,7 +1095,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
                        goto out_close;
                }
                info_buf->Attributes = cpu_to_le32(dosattr);
-               rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
+               rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
                                        current->tgid);
                /* although we would like to mark the file hidden
                   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,
        }
 
        /* rename the file */
-       rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
+       rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
+                                  cifs_sb->local_nls,
                                   cifs_sb->mnt_cifs_flags &
                                            CIFS_MOUNT_MAP_SPECIAL_CHR);
        if (rc != 0) {
@@ -1100,7 +1117,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
 
        /* try to set DELETE_ON_CLOSE */
        if (!cifsInode->delete_pending) {
-               rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
+               rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
                                               current->tgid);
                /*
                 * 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,
        }
 
 out_close:
-       CIFSSMBClose(xid, tcon, netfid);
+       CIFSSMBClose(xid, tcon, fid.netfid);
 out:
        kfree(info_buf);
        cifs_put_tlink(tlink);
@@ -1132,13 +1149,13 @@ out:
         * them anyway.
         */
 undo_rename:
-       CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
+       CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
                                cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
                                            CIFS_MOUNT_MAP_SPECIAL_CHR);
 undo_setattr:
        if (dosattr != origattr) {
                info_buf->Attributes = cpu_to_le32(origattr);
-               if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
+               if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
                                        current->tgid))
                        cifsInode->cifsAttrs = origattr;
        }
@@ -1549,7 +1566,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
        struct tcon_link *tlink;
        struct cifs_tcon *tcon;
        struct TCP_Server_Info *server;
-       __u16 srcfid;
+       struct cifs_fid fid;
+       struct cifs_open_parms oparms;
        int oplock, rc;
 
        tlink = cifs_sb_tlink(cifs_sb);
@@ -1576,17 +1594,23 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
        if (to_dentry->d_parent != from_dentry->d_parent)
                goto do_rename_exit;
 
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
        /* open the file to be renamed -- we need DELETE perms */
-       rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE,
-                        CREATE_NOT_DIR, &srcfid, &oplock, NULL,
-                        cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
-                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+       oparms.desired_access = DELETE;
+       oparms.create_options = CREATE_NOT_DIR;
+       oparms.disposition = FILE_OPEN;
+       oparms.path = from_path;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
+
+       rc = CIFS_open(xid, &oparms, &oplock, NULL);
        if (rc == 0) {
-               rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
+               rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
                                (const char *) to_dentry->d_name.name,
                                cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
-               CIFSSMBClose(xid, tcon, srcfid);
+               CIFSSMBClose(xid, tcon, fid.netfid);
        }
 do_rename_exit:
        cifs_put_tlink(tlink);
index 92aee08483a52e100011fb05e1fcfc5255b340ac..264ece71bdb20673d331c9335350705505d6e3fd 100644 (file)
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
 
+/*
+ * M-F Symlink Functions - Begin
+ */
+
 #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
 #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
 #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
@@ -91,10 +95,8 @@ symlink_hash_err:
 }
 
 static int
-CIFSParseMFSymlink(const u8 *buf,
-                  unsigned int buf_len,
-                  unsigned int *_link_len,
-                  char **_link_str)
+parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
+                char **_link_str)
 {
        int rc;
        unsigned int link_len;
@@ -137,7 +139,7 @@ CIFSParseMFSymlink(const u8 *buf,
 }
 
 static int
-CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
+format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)
 {
        int rc;
        unsigned int link_len;
@@ -180,190 +182,94 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
        return 0;
 }
 
+bool
+couldbe_mf_symlink(const struct cifs_fattr *fattr)
+{
+       if (!S_ISREG(fattr->cf_mode))
+               /* it's not a symlink */
+               return false;
+
+       if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
+               /* it's not a symlink */
+               return false;
+
+       return true;
+}
+
 static int
-CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon,
-                   const char *fromName, const char *toName,
-                   struct cifs_sb_info *cifs_sb)
+create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
+                 struct cifs_sb_info *cifs_sb, const char *fromName,
+                 const char *toName)
 {
        int rc;
-       int oplock = 0;
-       int remap;
-       int create_options = CREATE_NOT_DIR;
-       __u16 netfid = 0;
        u8 *buf;
        unsigned int bytes_written = 0;
-       struct cifs_io_parms io_parms;
-       struct nls_table *nls_codepage;
-
-       nls_codepage = cifs_sb->local_nls;
-       remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
 
        buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
 
-       rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
-       if (rc != 0) {
-               kfree(buf);
-               return rc;
-       }
-
-       if (backup_cred(cifs_sb))
-               create_options |= CREATE_OPEN_BACKUP_INTENT;
-
-       rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
-                        create_options, &netfid, &oplock, NULL,
-                        nls_codepage, remap);
-       if (rc != 0) {
-               kfree(buf);
-               return rc;
-       }
-
-       io_parms.netfid = netfid;
-       io_parms.pid = current->tgid;
-       io_parms.tcon = tcon;
-       io_parms.offset = 0;
-       io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
+       rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
+       if (rc)
+               goto out;
 
-       rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0);
-       CIFSSMBClose(xid, tcon, netfid);
-       kfree(buf);
-       if (rc != 0)
-               return rc;
+       rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb,
+                                       fromName, buf, &bytes_written);
+       if (rc)
+               goto out;
 
        if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
-               return -EIO;
-
-       return 0;
+               rc = -EIO;
+out:
+       kfree(buf);
+       return rc;
 }
 
 static int
-CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon,
-                  const unsigned char *searchName, char **symlinkinfo,
-                  const struct nls_table *nls_codepage, int remap)
+query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
+                struct cifs_sb_info *cifs_sb, const unsigned char *path,
+                char **symlinkinfo)
 {
        int rc;
-       int oplock = 0;
-       __u16 netfid = 0;
-       u8 *buf;
-       char *pbuf;
-       unsigned int bytes_read = 0;
-       int buf_type = CIFS_NO_BUFFER;
+       u8 *buf = NULL;
        unsigned int link_len = 0;
-       struct cifs_io_parms io_parms;
-       FILE_ALL_INFO file_info;
-
-       rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
-                        CREATE_NOT_DIR, &netfid, &oplock, &file_info,
-                        nls_codepage, remap);
-       if (rc != 0)
-               return rc;
-
-       if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
-               CIFSSMBClose(xid, tcon, netfid);
-               /* it's not a symlink */
-               return -EINVAL;
-       }
+       unsigned int bytes_read = 0;
 
        buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
-       pbuf = buf;
-       io_parms.netfid = netfid;
-       io_parms.pid = current->tgid;
-       io_parms.tcon = tcon;
-       io_parms.offset = 0;
-       io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
-
-       rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
-       CIFSSMBClose(xid, tcon, netfid);
-       if (rc != 0) {
-               kfree(buf);
-               return rc;
-       }
-
-       rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo);
-       kfree(buf);
-       if (rc != 0)
-               return rc;
-
-       return 0;
-}
-
-bool
-CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr)
-{
-       if (!(fattr->cf_mode & S_IFREG))
-               /* it's not a symlink */
-               return false;
 
-       if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
-               /* it's not a symlink */
-               return false;
-
-       return true;
-}
-
-int
-open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
-                       unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
-                       unsigned int xid)
-{
-       int rc;
-       int oplock = 0;
-       __u16 netfid = 0;
-       struct tcon_link *tlink;
-       struct cifs_tcon *ptcon;
-       struct cifs_io_parms io_parms;
-       int buf_type = CIFS_NO_BUFFER;
-       FILE_ALL_INFO file_info;
-
-       tlink = cifs_sb_tlink(cifs_sb);
-       if (IS_ERR(tlink))
-               return PTR_ERR(tlink);
-       ptcon = tlink_tcon(tlink);
+       if (tcon->ses->server->ops->query_mf_symlink)
+               rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
+                                             cifs_sb, path, buf, &bytes_read);
+       else
+               rc = -ENOSYS;
 
-       rc = CIFSSMBOpen(xid, ptcon, path, FILE_OPEN, GENERIC_READ,
-                        CREATE_NOT_DIR, &netfid, &oplock, &file_info,
-                        cifs_sb->local_nls,
-                        cifs_sb->mnt_cifs_flags &
-                               CIFS_MOUNT_MAP_SPECIAL_CHR);
-       if (rc != 0) {
-               cifs_put_tlink(tlink);
-               return rc;
-       }
+       if (rc)
+               goto out;
 
-       if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
-               CIFSSMBClose(xid, ptcon, netfid);
-               cifs_put_tlink(tlink);
-               /* it's not a symlink */
-               return rc;
+       if (bytes_read == 0) { /* not a symlink */
+               rc = -EINVAL;
+               goto out;
        }
 
-       io_parms.netfid = netfid;
-       io_parms.pid = current->tgid;
-       io_parms.tcon = ptcon;
-       io_parms.offset = 0;
-       io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
-
-       rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
-       CIFSSMBClose(xid, ptcon, netfid);
-       cifs_put_tlink(tlink);
+       rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo);
+out:
+       kfree(buf);
        return rc;
 }
 
-
 int
-CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
-                  struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
-                  const unsigned char *path)
+check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+                struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
+                const unsigned char *path)
 {
        int rc;
        u8 *buf = NULL;
        unsigned int link_len = 0;
        unsigned int bytes_read = 0;
 
-       if (!CIFSCouldBeMFSymlink(fattr))
+       if (!couldbe_mf_symlink(fattr))
                /* it's not a symlink */
                return 0;
 
@@ -372,8 +278,8 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
                return -ENOMEM;
 
        if (tcon->ses->server->ops->query_mf_symlink)
-               rc = tcon->ses->server->ops->query_mf_symlink(path, buf,
-                                               &bytes_read, cifs_sb, xid);
+               rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
+                                             cifs_sb, path, buf, &bytes_read);
        else
                rc = -ENOSYS;
 
@@ -383,7 +289,7 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
        if (bytes_read == 0) /* not a symlink */
                goto out;
 
-       rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
+       rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL);
        if (rc == -EINVAL) {
                /* it's not a symlink */
                rc = 0;
@@ -403,6 +309,95 @@ out:
        return rc;
 }
 
+/*
+ * SMB 1.0 Protocol specific functions
+ */
+
+int
+cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+                     struct cifs_sb_info *cifs_sb, const unsigned char *path,
+                     char *pbuf, unsigned int *pbytes_read)
+{
+       int rc;
+       int oplock = 0;
+       struct cifs_fid fid;
+       struct cifs_open_parms oparms;
+       struct cifs_io_parms io_parms;
+       int buf_type = CIFS_NO_BUFFER;
+       FILE_ALL_INFO file_info;
+
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
+       oparms.desired_access = GENERIC_READ;
+       oparms.create_options = CREATE_NOT_DIR;
+       oparms.disposition = FILE_OPEN;
+       oparms.path = path;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
+
+       rc = CIFS_open(xid, &oparms, &oplock, &file_info);
+       if (rc)
+               return rc;
+
+       if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE))
+               /* it's not a symlink */
+               goto out;
+
+       io_parms.netfid = fid.netfid;
+       io_parms.pid = current->tgid;
+       io_parms.tcon = tcon;
+       io_parms.offset = 0;
+       io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
+
+       rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
+out:
+       CIFSSMBClose(xid, tcon, fid.netfid);
+       return rc;
+}
+
+int
+cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+                      struct cifs_sb_info *cifs_sb, const unsigned char *path,
+                      char *pbuf, unsigned int *pbytes_written)
+{
+       int rc;
+       int oplock = 0;
+       struct cifs_fid fid;
+       struct cifs_open_parms oparms;
+       struct cifs_io_parms io_parms;
+       int create_options = CREATE_NOT_DIR;
+
+       if (backup_cred(cifs_sb))
+               create_options |= CREATE_OPEN_BACKUP_INTENT;
+
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
+       oparms.desired_access = GENERIC_WRITE;
+       oparms.create_options = create_options;
+       oparms.disposition = FILE_OPEN;
+       oparms.path = path;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
+
+       rc = CIFS_open(xid, &oparms, &oplock, NULL);
+       if (rc)
+               return rc;
+
+       io_parms.netfid = fid.netfid;
+       io_parms.pid = current->tgid;
+       io_parms.tcon = tcon;
+       io_parms.offset = 0;
+       io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
+
+       rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0);
+       CIFSSMBClose(xid, tcon, fid.netfid);
+       return rc;
+}
+
+/*
+ * M-F Symlink Functions - End
+ */
+
 int
 cifs_hardlink(struct dentry *old_file, struct inode *inode,
              struct dentry *direntry)
@@ -438,8 +433,10 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
        else {
                server = tcon->ses->server;
-               if (!server->ops->create_hardlink)
-                       return -ENOSYS;
+               if (!server->ops->create_hardlink) {
+                       rc = -ENOSYS;
+                       goto cifs_hl_exit;
+               }
                rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
                                                  cifs_sb);
                if ((rc == -EIO) || (rc == -EINVAL))
@@ -530,15 +527,10 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
         * and fallback to UNIX Extensions Symlinks.
         */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
-               rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path,
-                                       cifs_sb->local_nls,
-                                       cifs_sb->mnt_cifs_flags &
-                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+               rc = query_mf_symlink(xid, tcon, cifs_sb, full_path,
+                                     &target_path);
 
-       if ((rc != 0) && cap_unix(tcon->ses))
-               rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
-                                            cifs_sb->local_nls);
-       else if (rc != 0 && server->ops->query_symlink)
+       if (rc != 0 && server->ops->query_symlink)
                rc = server->ops->query_symlink(xid, tcon, full_path,
                                                &target_path, cifs_sb);
 
@@ -587,8 +579,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
 
        /* BB what if DFS and this volume is on different share? BB */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
-               rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname,
-                                       cifs_sb);
+               rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
        else if (pTcon->unix_ext)
                rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
                                           cifs_sb->local_nls);
index 5940ecabbe6a4f538f7dc91c334ed3017235e4dd..b15862e0f68c3c749a7cf6278dc6d3666ba71ccc 100644 (file)
@@ -749,7 +749,7 @@ static int cifs_filldir(char *find_entry, struct file *file,
        }
 
        if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
-           CIFSCouldBeMFSymlink(&fattr))
+           couldbe_mf_symlink(&fattr))
                /*
                 * trying to get the type and mode can be slow,
                 * so just call those regular files for now, and mark
index 5f5ba0dc2ee1b9c7b3d26ede9590a185ac6925e0..9ac5bfc9cc56af6ee74f9f3d2e15e66ab2dd2e54 100644 (file)
@@ -560,17 +560,24 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
        if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) {
                int tmprc;
                int oplock = 0;
-               __u16 netfid;
+               struct cifs_fid fid;
+               struct cifs_open_parms oparms;
+
+               oparms.tcon = tcon;
+               oparms.cifs_sb = cifs_sb;
+               oparms.desired_access = FILE_READ_ATTRIBUTES;
+               oparms.create_options = 0;
+               oparms.disposition = FILE_OPEN;
+               oparms.path = full_path;
+               oparms.fid = &fid;
+               oparms.reconnect = false;
 
                /* Need to check if this is a symbolic link or not */
-               tmprc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
-                                   FILE_READ_ATTRIBUTES, 0, &netfid, &oplock,
-                                   NULL, cifs_sb->local_nls,
-                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+               tmprc = CIFS_open(xid, &oparms, &oplock, NULL);
                if (tmprc == -EOPNOTSUPP)
                        *symlink = true;
                else
-                       CIFSSMBClose(xid, tcon, netfid);
+                       CIFSSMBClose(xid, tcon, fid.netfid);
        }
 
        return rc;
@@ -705,12 +712,7 @@ cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
                                     oparms->cifs_sb->local_nls,
                                     oparms->cifs_sb->mnt_cifs_flags
                                                & CIFS_MOUNT_MAP_SPECIAL_CHR);
-       return CIFSSMBOpen(xid, oparms->tcon, oparms->path,
-                          oparms->disposition, oparms->desired_access,
-                          oparms->create_options, &oparms->fid->netfid, oplock,
-                          buf, oparms->cifs_sb->local_nls,
-                          oparms->cifs_sb->mnt_cifs_flags &
-                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+       return CIFS_open(xid, oparms, oplock, buf);
 }
 
 static void
@@ -761,8 +763,9 @@ smb_set_file_info(struct inode *inode, const char *full_path,
 {
        int oplock = 0;
        int rc;
-       __u16 netfid;
        __u32 netpid;
+       struct cifs_fid fid;
+       struct cifs_open_parms oparms;
        struct cifsFileInfo *open_file;
        struct cifsInodeInfo *cinode = CIFS_I(inode);
        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,
        /* if the file is already open for write, just use that fileid */
        open_file = find_writable_file(cinode, true);
        if (open_file) {
-               netfid = open_file->fid.netfid;
+               fid.netfid = open_file->fid.netfid;
                netpid = open_file->pid;
                tcon = tlink_tcon(open_file->tlink);
                goto set_via_filehandle;
@@ -796,12 +799,17 @@ smb_set_file_info(struct inode *inode, const char *full_path,
                goto out;
        }
 
-       cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n");
-       rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
-                        SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
-                        &netfid, &oplock, NULL, cifs_sb->local_nls,
-                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
+       oparms.desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES;
+       oparms.create_options = CREATE_NOT_DIR;
+       oparms.disposition = FILE_OPEN;
+       oparms.path = full_path;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
 
+       cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n");
+       rc = CIFS_open(xid, &oparms, &oplock, NULL);
        if (rc != 0) {
                if (rc == -EIO)
                        rc = -EINVAL;
@@ -811,12 +819,12 @@ smb_set_file_info(struct inode *inode, const char *full_path,
        netpid = current->tgid;
 
 set_via_filehandle:
-       rc = CIFSSMBSetFileInfo(xid, tcon, buf, netfid, netpid);
+       rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid);
        if (!rc)
                cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
 
        if (open_file == NULL)
-               CIFSSMBClose(xid, tcon, netfid);
+               CIFSSMBClose(xid, tcon, fid.netfid);
        else
                cifsFileInfo_put(open_file);
 out:
@@ -907,6 +915,33 @@ cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
                           (__u8)type, wait, 0);
 }
 
+static int
+cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon,
+                      const unsigned char *searchName, char **symlinkinfo,
+                      const struct nls_table *nls_codepage)
+{
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       int rc;
+       unsigned int num_referrals = 0;
+       struct dfs_info3_param *referrals = NULL;
+
+       rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage,
+                         &num_referrals, &referrals, 0);
+
+       if (!rc && num_referrals > 0) {
+               *symlinkinfo = kstrndup(referrals->node_name,
+                                       strlen(referrals->node_name),
+                                       GFP_KERNEL);
+               if (!*symlinkinfo)
+                       rc = -ENOMEM;
+               free_dfs_info_array(referrals, num_referrals);
+       }
+       return rc;
+#else /* No DFS support */
+       return -EREMOTE;
+#endif
+}
+
 static int
 cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
                   const char *full_path, char **target_path,
@@ -914,27 +949,47 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 {
        int rc;
        int oplock = 0;
-       __u16 netfid;
+       struct cifs_fid fid;
+       struct cifs_open_parms oparms;
 
        cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
 
-       rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
-                        FILE_READ_ATTRIBUTES, OPEN_REPARSE_POINT, &netfid,
-                        &oplock, NULL, cifs_sb->local_nls,
-                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+       /* Check for unix extensions */
+       if (cap_unix(tcon->ses)) {
+               rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
+                                            cifs_sb->local_nls);
+               if (rc == -EREMOTE)
+                       rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
+                                                   target_path,
+                                                   cifs_sb->local_nls);
+
+               goto out;
+       }
+
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
+       oparms.desired_access = FILE_READ_ATTRIBUTES;
+       oparms.create_options = OPEN_REPARSE_POINT;
+       oparms.disposition = FILE_OPEN;
+       oparms.path = full_path;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
+
+       rc = CIFS_open(xid, &oparms, &oplock, NULL);
        if (rc)
-               return rc;
+               goto out;
 
-       rc = CIFSSMBQuerySymLink(xid, tcon, netfid, target_path,
+       rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path,
                                 cifs_sb->local_nls);
-       if (rc) {
-               CIFSSMBClose(xid, tcon, netfid);
-               return rc;
-       }
+       if (rc)
+               goto out_close;
 
        convert_delimiter(*target_path, '/');
-       CIFSSMBClose(xid, tcon, netfid);
-       cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+out_close:
+       CIFSSMBClose(xid, tcon, fid.netfid);
+out:
+       if (!rc)
+               cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
        return rc;
 }
 
@@ -1009,7 +1064,8 @@ struct smb_version_operations smb1_operations = {
        .mand_lock = cifs_mand_lock,
        .mand_unlock_range = cifs_unlock_range,
        .push_mand_locks = cifs_push_mandatory_locks,
-       .query_mf_symlink = open_query_close_cifs_symlink,
+       .query_mf_symlink = cifs_query_mf_symlink,
+       .create_mf_symlink = cifs_create_mf_symlink,
        .is_read_op = cifs_is_read_op,
 };
 
index 09afda4cc58e67aa0627bc3ba7c70167cd4ae73f..95c43bb203353a65974a6cf5b24a0fe02c3c5c86 100644 (file)
@@ -82,9 +82,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
                        goto remove_ea_exit;
 
                ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
-               rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,
-                       (__u16)0, cifs_sb->local_nls,
-                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+               if (pTcon->ses->server->ops->set_EA)
+                       rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
+                               full_path, ea_name, NULL, (__u16)0,
+                               cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
        }
 remove_ea_exit:
        kfree(full_path);
@@ -149,18 +151,22 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
                        cifs_dbg(FYI, "attempt to set cifs inode metadata\n");
 
                ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
-               rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
-                       (__u16)value_size, cifs_sb->local_nls,
-                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+               if (pTcon->ses->server->ops->set_EA)
+                       rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
+                               full_path, ea_name, ea_value, (__u16)value_size,
+                               cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
        } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)
                   == 0) {
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
                        goto set_ea_exit;
 
                ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
-               rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
-                       (__u16)value_size, cifs_sb->local_nls,
-                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+               if (pTcon->ses->server->ops->set_EA)
+                       rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
+                               full_path, ea_name, ea_value, (__u16)value_size,
+                               cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
        } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
                        strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
 #ifdef CONFIG_CIFS_ACL
@@ -272,17 +278,21 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
                        /* revalidate/getattr then populate from inode */
                } /* BB add else when above is implemented */
                ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
-               rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
-                       buf_size, cifs_sb->local_nls,
-                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+               if (pTcon->ses->server->ops->query_all_EAs)
+                       rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
+                               full_path, ea_name, ea_value, buf_size,
+                               cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
        } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
                        goto get_ea_exit;
 
                ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
-               rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
-                       buf_size, cifs_sb->local_nls,
-                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+               if (pTcon->ses->server->ops->query_all_EAs)
+                       rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
+                               full_path, ea_name, ea_value, buf_size,
+                               cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
        } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
                          strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
 #ifdef CONFIG_CIFS_POSIX
@@ -400,11 +410,12 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
        /* if proc/fs/cifs/streamstoxattr is set then
                search server for EAs or streams to
                returns as xattrs */
-       rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data,
-                               buf_size, cifs_sb->local_nls,
-                               cifs_sb->mnt_cifs_flags &
-                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
 
+       if (pTcon->ses->server->ops->query_all_EAs)
+               rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
+                               full_path, NULL, data, buf_size,
+                               cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
 list_ea_exit:
        kfree(full_path);
        free_xid(xid);