@@ -224,7 +224,8 @@ static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
224224
225225static noinline int create_subvol (struct btrfs_root * root ,
226226 struct dentry * dentry ,
227- char * name , int namelen )
227+ char * name , int namelen ,
228+ u64 * async_transid )
228229{
229230 struct btrfs_trans_handle * trans ;
230231 struct btrfs_key key ;
@@ -338,13 +339,19 @@ static noinline int create_subvol(struct btrfs_root *root,
338339
339340 d_instantiate (dentry , btrfs_lookup_dentry (dir , dentry ));
340341fail :
341- err = btrfs_commit_transaction (trans , root );
342+ if (async_transid ) {
343+ * async_transid = trans -> transid ;
344+ err = btrfs_commit_transaction_async (trans , root , 1 );
345+ } else {
346+ err = btrfs_commit_transaction (trans , root );
347+ }
342348 if (err && !ret )
343349 ret = err ;
344350 return ret ;
345351}
346352
347- static int create_snapshot (struct btrfs_root * root , struct dentry * dentry )
353+ static int create_snapshot (struct btrfs_root * root , struct dentry * dentry ,
354+ char * name , int namelen , u64 * async_transid )
348355{
349356 struct inode * inode ;
350357 struct btrfs_pending_snapshot * pending_snapshot ;
@@ -373,7 +380,14 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry)
373380
374381 list_add (& pending_snapshot -> list ,
375382 & trans -> transaction -> pending_snapshots );
376- ret = btrfs_commit_transaction (trans , root -> fs_info -> extent_root );
383+ if (async_transid ) {
384+ * async_transid = trans -> transid ;
385+ ret = btrfs_commit_transaction_async (trans ,
386+ root -> fs_info -> extent_root , 1 );
387+ } else {
388+ ret = btrfs_commit_transaction (trans ,
389+ root -> fs_info -> extent_root );
390+ }
377391 BUG_ON (ret );
378392
379393 ret = pending_snapshot -> error ;
@@ -412,7 +426,8 @@ static inline int btrfs_may_create(struct inode *dir, struct dentry *child)
412426 */
413427static noinline int btrfs_mksubvol (struct path * parent ,
414428 char * name , int namelen ,
415- struct btrfs_root * snap_src )
429+ struct btrfs_root * snap_src ,
430+ u64 * async_transid )
416431{
417432 struct inode * dir = parent -> dentry -> d_inode ;
418433 struct dentry * dentry ;
@@ -443,10 +458,11 @@ static noinline int btrfs_mksubvol(struct path *parent,
443458 goto out_up_read ;
444459
445460 if (snap_src ) {
446- error = create_snapshot (snap_src , dentry );
461+ error = create_snapshot (snap_src , dentry ,
462+ name , namelen , async_transid );
447463 } else {
448464 error = create_subvol (BTRFS_I (dir )-> root , dentry ,
449- name , namelen );
465+ name , namelen , async_transid );
450466 }
451467 if (!error )
452468 fsnotify_mkdir (dir , dentry );
@@ -799,35 +815,32 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
799815 return ret ;
800816}
801817
802- static noinline int btrfs_ioctl_snap_create (struct file * file ,
803- void __user * arg , int subvol )
818+ static noinline int btrfs_ioctl_snap_create_transid (struct file * file ,
819+ char * name ,
820+ unsigned long fd ,
821+ int subvol ,
822+ u64 * transid )
804823{
805824 struct btrfs_root * root = BTRFS_I (fdentry (file )-> d_inode )-> root ;
806- struct btrfs_ioctl_vol_args * vol_args ;
807825 struct file * src_file ;
808826 int namelen ;
809827 int ret = 0 ;
810828
811829 if (root -> fs_info -> sb -> s_flags & MS_RDONLY )
812830 return - EROFS ;
813831
814- vol_args = memdup_user (arg , sizeof (* vol_args ));
815- if (IS_ERR (vol_args ))
816- return PTR_ERR (vol_args );
817-
818- vol_args -> name [BTRFS_PATH_NAME_MAX ] = '\0' ;
819- namelen = strlen (vol_args -> name );
820- if (strchr (vol_args -> name , '/' )) {
832+ namelen = strlen (name );
833+ if (strchr (name , '/' )) {
821834 ret = - EINVAL ;
822835 goto out ;
823836 }
824837
825838 if (subvol ) {
826- ret = btrfs_mksubvol (& file -> f_path , vol_args -> name , namelen ,
827- NULL );
839+ ret = btrfs_mksubvol (& file -> f_path , name , namelen ,
840+ NULL , transid );
828841 } else {
829842 struct inode * src_inode ;
830- src_file = fget (vol_args -> fd );
843+ src_file = fget (fd );
831844 if (!src_file ) {
832845 ret = - EINVAL ;
833846 goto out ;
@@ -841,12 +854,56 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
841854 fput (src_file );
842855 goto out ;
843856 }
844- ret = btrfs_mksubvol (& file -> f_path , vol_args -> name , namelen ,
845- BTRFS_I (src_inode )-> root );
857+ ret = btrfs_mksubvol (& file -> f_path , name , namelen ,
858+ BTRFS_I (src_inode )-> root ,
859+ transid );
846860 fput (src_file );
847861 }
848862out :
863+ return ret ;
864+ }
865+
866+ static noinline int btrfs_ioctl_snap_create (struct file * file ,
867+ void __user * arg , int subvol ,
868+ int async )
869+ {
870+ struct btrfs_ioctl_vol_args * vol_args = NULL ;
871+ struct btrfs_ioctl_async_vol_args * async_vol_args = NULL ;
872+ char * name ;
873+ u64 fd ;
874+ u64 transid = 0 ;
875+ int ret ;
876+
877+ if (async ) {
878+ async_vol_args = memdup_user (arg , sizeof (* async_vol_args ));
879+ if (IS_ERR (async_vol_args ))
880+ return PTR_ERR (async_vol_args );
881+
882+ name = async_vol_args -> name ;
883+ fd = async_vol_args -> fd ;
884+ async_vol_args -> name [BTRFS_SNAPSHOT_NAME_MAX ] = '\0' ;
885+ } else {
886+ vol_args = memdup_user (arg , sizeof (* vol_args ));
887+ if (IS_ERR (vol_args ))
888+ return PTR_ERR (vol_args );
889+ name = vol_args -> name ;
890+ fd = vol_args -> fd ;
891+ vol_args -> name [BTRFS_PATH_NAME_MAX ] = '\0' ;
892+ }
893+
894+ ret = btrfs_ioctl_snap_create_transid (file , name , fd ,
895+ subvol , & transid );
896+
897+ if (!ret && async ) {
898+ if (copy_to_user (arg +
899+ offsetof(struct btrfs_ioctl_async_vol_args ,
900+ transid ), & transid , sizeof (transid )))
901+ return - EFAULT ;
902+ }
903+
849904 kfree (vol_args );
905+ kfree (async_vol_args );
906+
850907 return ret ;
851908}
852909
@@ -2072,9 +2129,11 @@ long btrfs_ioctl(struct file *file, unsigned int
20722129 case FS_IOC_GETVERSION :
20732130 return btrfs_ioctl_getversion (file , argp );
20742131 case BTRFS_IOC_SNAP_CREATE :
2075- return btrfs_ioctl_snap_create (file , argp , 0 );
2132+ return btrfs_ioctl_snap_create (file , argp , 0 , 0 );
2133+ case BTRFS_IOC_SNAP_CREATE_ASYNC :
2134+ return btrfs_ioctl_snap_create (file , argp , 0 , 1 );
20762135 case BTRFS_IOC_SUBVOL_CREATE :
2077- return btrfs_ioctl_snap_create (file , argp , 1 );
2136+ return btrfs_ioctl_snap_create (file , argp , 1 , 0 );
20782137 case BTRFS_IOC_SNAP_DESTROY :
20792138 return btrfs_ioctl_snap_destroy (file , argp );
20802139 case BTRFS_IOC_DEFAULT_SUBVOL :
0 commit comments