Merge tag 'mvebu-fixes-5.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/gclem...
[linux-2.6-microblaze.git] / fs / cifs / smb2ops.c
index ba3c58e..2dfd0d8 100644 (file)
@@ -3618,6 +3618,7 @@ static int smb3_simple_fallocate_write_range(unsigned int xid,
 {
        struct cifs_io_parms io_parms = {0};
        int nbytes;
+       int rc = 0;
        struct kvec iov[2];
 
        io_parms.netfid = cfile->fid.netfid;
@@ -3625,13 +3626,25 @@ static int smb3_simple_fallocate_write_range(unsigned int xid,
        io_parms.tcon = tcon;
        io_parms.persistent_fid = cfile->fid.persistent_fid;
        io_parms.volatile_fid = cfile->fid.volatile_fid;
-       io_parms.offset = off;
-       io_parms.length = len;
 
-       /* iov[0] is reserved for smb header */
-       iov[1].iov_base = buf;
-       iov[1].iov_len = io_parms.length;
-       return SMB2_write(xid, &io_parms, &nbytes, iov, 1);
+       while (len) {
+               io_parms.offset = off;
+               io_parms.length = len;
+               if (io_parms.length > SMB2_MAX_BUFFER_SIZE)
+                       io_parms.length = SMB2_MAX_BUFFER_SIZE;
+               /* iov[0] is reserved for smb header */
+               iov[1].iov_base = buf;
+               iov[1].iov_len = io_parms.length;
+               rc = SMB2_write(xid, &io_parms, &nbytes, iov, 1);
+               if (rc)
+                       break;
+               if (nbytes > len)
+                       return -EINVAL;
+               buf += nbytes;
+               off += nbytes;
+               len -= nbytes;
+       }
+       return rc;
 }
 
 static int smb3_simple_fallocate_range(unsigned int xid,
@@ -3655,11 +3668,6 @@ static int smb3_simple_fallocate_range(unsigned int xid,
                        (char **)&out_data, &out_data_len);
        if (rc)
                goto out;
-       /*
-        * It is already all allocated
-        */
-       if (out_data_len == 0)
-               goto out;
 
        buf = kzalloc(1024 * 1024, GFP_KERNEL);
        if (buf == NULL) {
@@ -3782,6 +3790,24 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
                goto out;
        }
 
+       if (keep_size == true) {
+               /*
+                * We can not preallocate pages beyond the end of the file
+                * in SMB2
+                */
+               if (off >= i_size_read(inode)) {
+                       rc = 0;
+                       goto out;
+               }
+               /*
+                * For fallocates that are partially beyond the end of file,
+                * clamp len so we only fallocate up to the end of file.
+                */
+               if (off + len > i_size_read(inode)) {
+                       len = i_size_read(inode) - off;
+               }
+       }
+
        if ((keep_size == true) || (i_size_read(inode) >= off + len)) {
                /*
                 * At this point, we are trying to fallocate an internal