@@ -848,42 +848,67 @@ static const struct afs_operation_ops afs_setattr_operation = {
848848int afs_setattr (struct user_namespace * mnt_userns , struct dentry * dentry ,
849849 struct iattr * attr )
850850{
851+ const unsigned int supported =
852+ ATTR_SIZE | ATTR_MODE | ATTR_UID | ATTR_GID |
853+ ATTR_MTIME | ATTR_MTIME_SET | ATTR_TIMES_SET | ATTR_TOUCH ;
851854 struct afs_operation * op ;
852855 struct afs_vnode * vnode = AFS_FS_I (d_inode (dentry ));
856+ struct inode * inode = & vnode -> vfs_inode ;
857+ loff_t i_size ;
853858 int ret ;
854859
855860 _enter ("{%llx:%llu},{n=%pd},%x" ,
856861 vnode -> fid .vid , vnode -> fid .vnode , dentry ,
857862 attr -> ia_valid );
858863
859- if (!(attr -> ia_valid & (ATTR_SIZE | ATTR_MODE | ATTR_UID | ATTR_GID |
860- ATTR_MTIME | ATTR_MTIME_SET | ATTR_TIMES_SET |
861- ATTR_TOUCH ))) {
864+ if (!(attr -> ia_valid & supported )) {
862865 _leave (" = 0 [unsupported]" );
863866 return 0 ;
864867 }
865868
869+ i_size = i_size_read (inode );
866870 if (attr -> ia_valid & ATTR_SIZE ) {
867- if (!S_ISREG (vnode -> vfs_inode . i_mode ))
871+ if (!S_ISREG (inode -> i_mode ))
868872 return - EISDIR ;
869873
870- ret = inode_newsize_ok (& vnode -> vfs_inode , attr -> ia_size );
874+ ret = inode_newsize_ok (inode , attr -> ia_size );
871875 if (ret )
872876 return ret ;
873877
874- if (attr -> ia_size == i_size_read ( & vnode -> vfs_inode ) )
878+ if (attr -> ia_size == i_size )
875879 attr -> ia_valid &= ~ATTR_SIZE ;
876880 }
877881
878882 fscache_use_cookie (afs_vnode_cache (vnode ), true);
879883
880- /* flush any dirty data outstanding on a regular file */
881- if (S_ISREG (vnode -> vfs_inode .i_mode ))
882- filemap_write_and_wait (vnode -> vfs_inode .i_mapping );
883-
884884 /* Prevent any new writebacks from starting whilst we do this. */
885885 down_write (& vnode -> validate_lock );
886886
887+ if ((attr -> ia_valid & ATTR_SIZE ) && S_ISREG (inode -> i_mode )) {
888+ loff_t size = attr -> ia_size ;
889+
890+ /* Wait for any outstanding writes to the server to complete */
891+ loff_t from = min (size , i_size );
892+ loff_t to = max (size , i_size );
893+ ret = filemap_fdatawait_range (inode -> i_mapping , from , to );
894+ if (ret < 0 )
895+ goto out_unlock ;
896+
897+ /* Don't talk to the server if we're just shortening in-memory
898+ * writes that haven't gone to the server yet.
899+ */
900+ if (!(attr -> ia_valid & (supported & ~ATTR_SIZE & ~ATTR_MTIME )) &&
901+ attr -> ia_size < i_size &&
902+ attr -> ia_size > vnode -> status .size ) {
903+ truncate_pagecache (inode , attr -> ia_size );
904+ fscache_resize_cookie (afs_vnode_cache (vnode ),
905+ attr -> ia_size );
906+ i_size_write (inode , attr -> ia_size );
907+ ret = 0 ;
908+ goto out_unlock ;
909+ }
910+ }
911+
887912 op = afs_alloc_operation (((attr -> ia_valid & ATTR_FILE ) ?
888913 afs_file_key (attr -> ia_file ) : NULL ),
889914 vnode -> volume );
0 commit comments