@@ -4073,19 +4073,14 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
40734073 goto retry ;
40744074 }
40754075out1 :
4076- #ifdef CONFIG_DEEPIN_ERR_NOTIFY
4077- if (unlikely ((error == - EROFS ) && deepin_err_notify_enabled ())) {
4078- struct path file_path ;
4079- int get_path_err ;
4080-
4081- get_path_err =
4082- deepin_get_path_for_err_notify (dfd , name , & file_path );
4083- if (!get_path_err ) {
4084- deepin_check_and_notify_ro_fs_err (& file_path , "mknod" );
4085- path_put (& file_path );
4076+ if (deepin_should_notify_ro_fs_err (error )) {
4077+ struct deepin_path_last path_last ;
4078+
4079+ if (!deepin_lookup_path_or_parent (dfd , name , lookup_flags , & path_last )) {
4080+ deepin_check_and_notify_ro_fs_err (& path_last , "mknod" );
4081+ deepin_put_path_last (& path_last );
40864082 }
40874083 }
4088- #endif /* CONFIG_DEEPIN_ERR_NOTIFY */
40894084 putname (name );
40904085 return error ;
40914086}
@@ -4169,19 +4164,14 @@ int do_mkdirat(int dfd, struct filename *name, umode_t mode)
41694164 goto retry ;
41704165 }
41714166out_putname :
4172- #ifdef CONFIG_DEEPIN_ERR_NOTIFY
4173- if (unlikely ((error == - EROFS ) && deepin_err_notify_enabled ())) {
4174- struct path file_path ;
4175- int get_path_err ;
4176-
4177- get_path_err =
4178- deepin_get_path_for_err_notify (dfd , name , & file_path );
4179- if (!get_path_err ) {
4180- deepin_check_and_notify_ro_fs_err (& file_path , "mkdir" );
4181- path_put (& file_path );
4167+ if (deepin_should_notify_ro_fs_err (error )) {
4168+ struct deepin_path_last path_last ;
4169+
4170+ if (!deepin_lookup_path_or_parent (dfd , name , lookup_flags , & path_last )) {
4171+ deepin_check_and_notify_ro_fs_err (& path_last , "mkdir" );
4172+ deepin_put_path_last (& path_last );
41824173 }
41834174 }
4184- #endif /* CONFIG_DEEPIN_ERR_NOTIFY */
41854175 putname (name );
41864176 return error ;
41874177}
@@ -4299,21 +4289,18 @@ int do_rmdir(int dfd, struct filename *name)
42994289 inode_unlock (path .dentry -> d_inode );
43004290 mnt_drop_write (path .mnt );
43014291exit2 :
4302- #ifdef CONFIG_DEEPIN_ERR_NOTIFY
4303- if (unlikely ((error == - EROFS ) && deepin_err_notify_enabled ())) {
4304- dentry = lookup_one_qstr_excl (& last , path .dentry , 0 );
4305- if (!IS_ERR (dentry )) {
4306- if (d_is_positive (dentry )) {
4307- // dentry is positive, so we can get the path
4308- struct path file_path = { .mnt = path .mnt ,
4309- .dentry = dentry };
4310- deepin_check_and_notify_ro_fs_err (& file_path ,
4292+ if (deepin_should_notify_ro_fs_err (error )) {
4293+ struct deepin_path_last path_last ;
4294+
4295+ if (!deepin_lookup_path_or_parent (dfd , name , lookup_flags , & path_last )) {
4296+ if (!path_last .last ) {
4297+ // File exists, notify error
4298+ deepin_check_and_notify_ro_fs_err (& path_last ,
43114299 "rmdir" );
43124300 }
4313- dput ( dentry );
4301+ deepin_put_path_last ( & path_last );
43144302 }
43154303 }
4316- #endif /* CONFIG_DEEPIN_ERR_NOTIFY */
43174304 path_put (& path );
43184305 if (retry_estale (error , lookup_flags )) {
43194306 lookup_flags |= LOOKUP_REVAL ;
@@ -4459,21 +4446,18 @@ int do_unlinkat(int dfd, struct filename *name)
44594446 }
44604447 mnt_drop_write (path .mnt );
44614448exit2 :
4462- #ifdef CONFIG_DEEPIN_ERR_NOTIFY
4463- if (unlikely ((error == - EROFS ) && deepin_err_notify_enabled ())) {
4464- dentry = lookup_one_qstr_excl (& last , path .dentry , 0 );
4465- if (!IS_ERR (dentry )) {
4466- if (d_is_positive (dentry )) {
4467- // dentry is positive, so we can get the path
4468- struct path file_path = { .mnt = path .mnt ,
4469- .dentry = dentry };
4470- deepin_check_and_notify_ro_fs_err (& file_path ,
4449+ if (deepin_should_notify_ro_fs_err (error )) {
4450+ struct deepin_path_last path_last ;
4451+
4452+ if (!deepin_lookup_path_or_parent (dfd , name , lookup_flags , & path_last )) {
4453+ if (!path_last .last ) {
4454+ // File exists, notify error
4455+ deepin_check_and_notify_ro_fs_err (& path_last ,
44714456 "unlink" );
44724457 }
4473- dput ( dentry );
4458+ deepin_put_path_last ( & path_last );
44744459 }
44754460 }
4476- #endif /* CONFIG_DEEPIN_ERR_NOTIFY */
44774461 path_put (& path );
44784462 if (retry_estale (error , lookup_flags )) {
44794463 lookup_flags |= LOOKUP_REVAL ;
@@ -4574,20 +4558,15 @@ int do_symlinkat(struct filename *from, int newdfd, struct filename *to)
45744558 goto retry ;
45754559 }
45764560out_putnames :
4577- #ifdef CONFIG_DEEPIN_ERR_NOTIFY
4578- if (unlikely ((error == - EROFS ) && deepin_err_notify_enabled ())) {
4579- struct path file_path ;
4580- int get_path_err ;
4581-
4582- get_path_err =
4583- deepin_get_path_for_err_notify (newdfd , to , & file_path );
4584- if (!get_path_err ) {
4585- deepin_check_and_notify_ro_fs_err (& file_path ,
4561+ if (deepin_should_notify_ro_fs_err (error )) {
4562+ struct deepin_path_last path_last ;
4563+
4564+ if (!deepin_lookup_path_or_parent (newdfd , to , lookup_flags , & path_last )) {
4565+ deepin_check_and_notify_ro_fs_err (& path_last ,
45864566 "symlink" );
4587- path_put ( & file_path );
4567+ deepin_put_path_last ( & path_last );
45884568 }
45894569 }
4590- #endif /* CONFIG_DEEPIN_ERR_NOTIFY */
45914570 putname (to );
45924571 putname (from );
45934572 return error ;
@@ -4766,19 +4745,14 @@ int do_linkat(int olddfd, struct filename *old, int newdfd,
47664745 goto retry ;
47674746 }
47684747out_putpath :
4769- #ifdef CONFIG_DEEPIN_ERR_NOTIFY
4770- if (unlikely ((error == - EROFS ) && deepin_err_notify_enabled ())) {
4771- struct path file_path ;
4772- int get_path_err ;
4773-
4774- get_path_err =
4775- deepin_get_path_for_err_notify (newdfd , new , & file_path );
4776- if (!get_path_err ) {
4777- deepin_check_and_notify_ro_fs_err (& file_path , "link" );
4778- path_put (& file_path );
4748+ if (deepin_should_notify_ro_fs_err (error )) {
4749+ struct deepin_path_last path_last ;
4750+
4751+ if (!deepin_lookup_path_or_parent (newdfd , new , how , & path_last )) {
4752+ deepin_check_and_notify_ro_fs_err (& path_last , "link" );
4753+ deepin_put_path_last (& path_last );
47794754 }
47804755 }
4781- #endif /* CONFIG_DEEPIN_ERR_NOTIFY */
47824756 path_put (& old_path );
47834757out_putnames :
47844758 putname (old );
@@ -5133,22 +5107,8 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd,
51335107 }
51345108 mnt_drop_write (old_path .mnt );
51355109exit2 :
5136- #ifdef CONFIG_DEEPIN_ERR_NOTIFY
5137- if (unlikely ((error == - EROFS ) && deepin_err_notify_enabled ())) {
5138- old_dentry =
5139- lookup_one_qstr_excl (& old_last , old_path .dentry , 0 );
5140- if (!IS_ERR (old_dentry )) {
5141- if (d_is_positive (old_dentry )) {
5142- struct path file_path = { .mnt = old_path .mnt ,
5143- .dentry =
5144- old_dentry };
5145- deepin_check_and_notify_ro_fs_err (& file_path ,
5146- "rename" );
5147- }
5148- dput (old_dentry );
5149- }
5150- }
5151- #endif /* CONFIG_DEEPIN_ERR_NOTIFY */
5110+ if (deepin_should_notify_ro_fs_err (error ))
5111+ deepin_notify_rename_ro_fs_err (& old_last , & new_last , & old_path , & new_path );
51525112 if (retry_estale (error , lookup_flags ))
51535113 should_retry = true;
51545114 path_put (& new_path );
@@ -5368,37 +5328,76 @@ const struct inode_operations page_symlink_inode_operations = {
53685328EXPORT_SYMBOL (page_symlink_inode_operations );
53695329
53705330#ifdef CONFIG_DEEPIN_ERR_NOTIFY
5371- int deepin_get_path_for_err_notify (int dfd , struct filename * name ,
5372- struct path * result_path )
5331+ /**
5332+ * deepin_lookup_path_or_parent - Prepare path info for read-only FS error notification
5333+ * @dfd: Directory file descriptor used as lookup base
5334+ * @name: Filename to look up (struct filename)
5335+ * @flags: Lookup flags (e.g., LOOKUP_DIRECTORY, LOOKUP_FOLLOW)
5336+ * @result_path_last: Output structure carrying the resolved parent path and
5337+ * optionally the last component string
5338+ *
5339+ * Memory/Lifetime management:
5340+ * - result_path_last->path:
5341+ * The path returned by filename_lookup() or filename_parentat() already
5342+ * holds a reference count. You MUST release it after use. Preferred:
5343+ * deepin_put_path_last(&pl), which will call path_put() for you.
5344+ * Alternatively, call path_put() manually if you manage the string separately.
5345+ *
5346+ * - result_path_last->last:
5347+ * In the -ENOENT (parent found) case, the last component string is duplicated
5348+ * via kstrdup() and MUST be freed with kfree(). deepin_put_path_last(&pl)
5349+ * will free it for you. If the full path was resolved, this field is set
5350+ * to NULL and no extra string free is needed.
5351+ *
5352+ * Recommended usage pattern:
5353+ * struct deepin_path_last pl;
5354+ * if (!deepin_lookup_path_or_parent(dfd, name, lookup_flags, &pl)) {
5355+ * deepin_check_and_notify_ro_fs_err(&pl, "op");
5356+ * deepin_put_path_last(&pl); // releases path and frees pl.last if allocated
5357+ * }
5358+ *
5359+ * Return: 0 on success, negative errno on failure.
5360+ */
5361+ int deepin_lookup_path_or_parent (int dfd , struct filename * name ,
5362+ unsigned int flags ,
5363+ struct deepin_path_last * result_path_last )
53735364{
5365+ struct path result_path ;
5366+ struct path parent ;
53745367 struct qstr last ;
5375- struct path parent_path ;
53765368 int type ;
5377- struct dentry * dentry ;
53785369 int error ;
53795370
5380- error = filename_parentat (dfd , name , 0 , & parent_path , & last , & type );
5371+ error = filename_lookup (dfd , name , flags , & result_path , NULL );
5372+ if (error == - ENOENT ) {
5373+ error = filename_parentat (dfd , name , flags , & parent , & last , & type );
5374+ if (error )
5375+ return error ;
5376+ if (unlikely (type != LAST_NORM )) {
5377+ path_put (& parent );
5378+ return - EINVAL ;
5379+ }
5380+ /* Duplicate the filename string to avoid dangling pointer */
5381+ result_path_last -> last = kstrdup ((const char * )last .name , GFP_KERNEL );
5382+ if (!result_path_last -> last ) {
5383+ path_put (& parent );
5384+ return - ENOMEM ;
5385+ }
5386+ result_path_last -> path = parent ;
5387+ return 0 ;
5388+ }
5389+
53815390 if (error )
53825391 return error ;
53835392
5384- dentry = lookup_one_qstr_excl (& last , parent_path .dentry , 0 );
5385- if (!IS_ERR (dentry )) {
5386- result_path -> mnt = parent_path .mnt ;
5387- result_path -> dentry = dentry ;
5388- path_get (result_path ); // Increment reference count
5389- dput (dentry );
5390- } else {
5391- // If the file does not exist, use the parent directory
5392- * result_path = parent_path ;
5393- path_get (result_path );
5394- }
5395-
5396- path_put (& parent_path );
5393+ result_path_last -> last = NULL ;
5394+ result_path_last -> path = result_path ;
53975395 return 0 ;
53985396}
53995397#else
5400- int deepin_get_path_for_err_notify (int dfd , struct filename * name ,
5401- struct path * result_path )
5398+ int deepin_lookup_path_or_parent (int dfd , struct filename * name ,
5399+ unsigned int flags ,
5400+ struct deepin_path_last * result_path_last )
54025401{
54035402 return - EOPNOTSUPP ;
54045403}
0 commit comments